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    source script_util.vim
27    XpathINIT
28    XloopINIT
29  END
30  let cleanup =<< trim END
31    call writefile(v:errors, 'Xtest.out')
32    qall
33  END
34  call writefile(init, 'Xtest.vim')
35  call writefile(a:test, 'Xtest.vim', 'a')
36  call writefile(a:verify, 'Xverify.vim')
37  call writefile(cleanup, 'Xverify.vim', 'a')
38  call RunVim([], [], "-S Xtest.vim -S Xverify.vim")
39  call assert_equal([], readfile('Xtest.out'))
40  call delete('Xtest.out')
41  call delete('Xtest.vim')
42  call delete('Xverify.vim')
43endfunc
44
45"-------------------------------------------------------------------------------
46" Test 1:   :endwhile in function					    {{{1
47"
48"	    Detect if a broken loop is (incorrectly) reactivated by the
49"	    :endwhile.  Use a :return to prevent an endless loop, and make
50"	    this test first to get a meaningful result on an error before other
51"	    tests will hang.
52"-------------------------------------------------------------------------------
53
54func T1_F()
55    Xpath 'a'
56    let first = 1
57    while 1
58	Xpath 'b'
59	if first
60	    Xpath 'c'
61	    let first = 0
62	    break
63	else
64	    Xpath 'd'
65	    return
66	endif
67    endwhile
68endfunc
69
70func T1_G()
71    Xpath 'h'
72    let first = 1
73    while 1
74	Xpath 'i'
75	if first
76	    Xpath 'j'
77	    let first = 0
78	    break
79	else
80	    Xpath 'k'
81	    return
82	endif
83	if 1	" unmatched :if
84    endwhile
85endfunc
86
87func Test_endwhile_function()
88  XpathINIT
89  call T1_F()
90  Xpath 'F'
91
92  try
93    call T1_G()
94  catch
95    " Catch missing :endif
96    call assert_true(v:exception =~ 'E171')
97    Xpath 'x'
98  endtry
99  Xpath 'G'
100
101  call assert_equal('abcFhijxG', g:Xpath)
102endfunc
103
104"-------------------------------------------------------------------------------
105" Test 2:   :endwhile in script						    {{{1
106"
107"	    Detect if a broken loop is (incorrectly) reactivated by the
108"	    :endwhile.  Use a :finish to prevent an endless loop, and place
109"	    this test before others that might hang to get a meaningful result
110"	    on an error.
111"
112"	    This test executes the bodies of the functions T1_F and T1_G from
113"	    the previous test as script files (:return replaced by :finish).
114"-------------------------------------------------------------------------------
115
116func Test_endwhile_script()
117  XpathINIT
118  ExecAsScript T1_F
119  Xpath 'F'
120  call DeleteTheScript()
121
122  try
123    ExecAsScript T1_G
124  catch
125    " Catch missing :endif
126    call assert_true(v:exception =~ 'E171')
127    Xpath 'x'
128  endtry
129  Xpath 'G'
130  call DeleteTheScript()
131
132  call assert_equal('abcFhijxG', g:Xpath)
133endfunc
134
135"-------------------------------------------------------------------------------
136" Test 3:   :if, :elseif, :while, :continue, :break			    {{{1
137"-------------------------------------------------------------------------------
138
139func Test_if_while()
140    XpathINIT
141    if 1
142	Xpath 'a'
143	let loops = 3
144	while loops > -1	    " main loop: loops == 3, 2, 1 (which breaks)
145	    if loops <= 0
146		let break_err = 1
147		let loops = -1
148	    else
149		Xpath 'b' . loops
150	    endif
151	    if (loops == 2)
152		while loops == 2 " dummy loop
153		    Xpath 'c' . loops
154		    let loops = loops - 1
155		    continue    " stop dummy loop
156		    Xpath 'd' . loops
157		endwhile
158		continue	    " continue main loop
159		Xpath 'e' . loops
160	    elseif (loops == 1)
161		let p = 1
162		while p	    " dummy loop
163		    Xpath 'f' . loops
164		    let p = 0
165		    break	    " break dummy loop
166		    Xpath 'g' . loops
167		endwhile
168		Xpath 'h' . loops
169		unlet p
170		break	    " break main loop
171		Xpath 'i' . loops
172	    endif
173	    if (loops > 0)
174		Xpath 'j' . loops
175	    endif
176	    while loops == 3    " dummy loop
177		let loops = loops - 1
178	    endwhile	    " end dummy loop
179	endwhile		    " end main loop
180	Xpath 'k'
181    else
182	Xpath 'l'
183    endif
184    Xpath 'm'
185    if exists("break_err")
186	Xpath 'm'
187	unlet break_err
188    endif
189
190    unlet loops
191
192    call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath)
193endfunc
194
195"-------------------------------------------------------------------------------
196" Test 4:   :return							    {{{1
197"-------------------------------------------------------------------------------
198
199func T4_F()
200    if 1
201	Xpath 'a'
202	let loops = 3
203	while loops > 0				"    3:  2:     1:
204	    Xpath 'b' . loops
205	    if (loops == 2)
206		Xpath 'c' . loops
207		return
208		Xpath 'd' . loops
209	    endif
210	    Xpath 'e' . loops
211	    let loops = loops - 1
212	endwhile
213	Xpath 'f'
214    else
215	Xpath 'g'
216    endif
217endfunc
218
219func Test_return()
220    XpathINIT
221    call T4_F()
222    Xpath '4'
223
224    call assert_equal('ab3e3b2c24', g:Xpath)
225endfunc
226
227
228"-------------------------------------------------------------------------------
229" Test 5:   :finish							    {{{1
230"
231"	    This test executes the body of the function T4_F from the previous
232"	    test as a script file (:return replaced by :finish).
233"-------------------------------------------------------------------------------
234
235func Test_finish()
236    XpathINIT
237    ExecAsScript T4_F
238    Xpath '5'
239    call DeleteTheScript()
240
241    call assert_equal('ab3e3b2c25', g:Xpath)
242endfunc
243
244
245
246"-------------------------------------------------------------------------------
247" Test 6:   Defining functions in :while loops				    {{{1
248"
249"	     Functions can be defined inside other functions.  An inner function
250"	     gets defined when the outer function is executed.  Functions may
251"	     also be defined inside while loops.  Expressions in braces for
252"	     defining the function name are allowed.
253"
254"	     The functions are defined when sourcing the script, only the
255"	     resulting path is checked in the test function.
256"-------------------------------------------------------------------------------
257
258XpathINIT
259
260" The command CALL collects the argument of all its invocations in "calls"
261" when used from a function (that is, when the global variable "calls" needs
262" the "g:" prefix).  This is to check that the function code is skipped when
263" the function is defined.  For inner functions, do so only if the outer
264" function is not being executed.
265"
266let calls = ""
267com! -nargs=1 CALL
268	    \ if !exists("calls") && !exists("outer") |
269	    \ let g:calls = g:calls . <args> |
270	    \ endif
271
272let i = 0
273while i < 3
274    let i = i + 1
275    if i == 1
276	Xpath 'a'
277	function! F1(arg)
278	    CALL a:arg
279	    let outer = 1
280
281	    let j = 0
282	    while j < 1
283		Xpath 'b'
284		let j = j + 1
285		function! G1(arg)
286		    CALL a:arg
287		endfunction
288		Xpath 'c'
289	    endwhile
290	endfunction
291	Xpath 'd'
292
293	continue
294    endif
295
296    Xpath 'e' . i
297    function! F{i}(i, arg)
298	CALL a:arg
299	let outer = 1
300
301	if a:i == 3
302	    Xpath 'f'
303	endif
304	let k = 0
305	while k < 3
306	    Xpath 'g' . k
307	    let k = k + 1
308	    function! G{a:i}{k}(arg)
309		CALL a:arg
310	    endfunction
311	    Xpath 'h' . k
312	endwhile
313    endfunction
314    Xpath 'i'
315
316endwhile
317
318if exists("*G1")
319    Xpath 'j'
320endif
321if exists("*F1")
322    call F1("F1")
323    if exists("*G1")
324       call G1("G1")
325    endif
326endif
327
328if exists("G21") || exists("G22") || exists("G23")
329    Xpath 'k'
330endif
331if exists("*F2")
332    call F2(2, "F2")
333    if exists("*G21")
334       call G21("G21")
335    endif
336    if exists("*G22")
337       call G22("G22")
338    endif
339    if exists("*G23")
340       call G23("G23")
341    endif
342endif
343
344if exists("G31") || exists("G32") || exists("G33")
345    Xpath 'l'
346endif
347if exists("*F3")
348    call F3(3, "F3")
349    if exists("*G31")
350       call G31("G31")
351    endif
352    if exists("*G32")
353       call G32("G32")
354    endif
355    if exists("*G33")
356       call G33("G33")
357    endif
358endif
359
360Xpath 'm'
361
362let g:test6_result = g:Xpath
363let g:test6_calls = calls
364
365unlet calls
366delfunction F1
367delfunction G1
368delfunction F2
369delfunction G21
370delfunction G22
371delfunction G23
372delfunction G31
373delfunction G32
374delfunction G33
375
376func Test_defining_functions()
377    call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result)
378    call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls)
379endfunc
380
381"-------------------------------------------------------------------------------
382" Test 7:   Continuing on errors outside functions			    {{{1
383"
384"	    On an error outside a function, the script processing continues
385"	    at the line following the outermost :endif or :endwhile.  When not
386"	    inside an :if or :while, the script processing continues at the next
387"	    line.
388"-------------------------------------------------------------------------------
389
390XpathINIT
391
392if 1
393    Xpath 'a'
394    while 1
395	Xpath 'b'
396	asdf
397	Xpath 'c'
398	break
399    endwhile | Xpath 'd'
400    Xpath 'e'
401endif | Xpath 'f'
402Xpath 'g'
403
404while 1
405    Xpath 'h'
406    if 1
407	Xpath 'i'
408	asdf
409	Xpath 'j'
410    endif | Xpath 'k'
411    Xpath 'l'
412    break
413endwhile | Xpath 'm'
414Xpath 'n'
415
416asdf
417Xpath 'o'
418
419asdf | Xpath 'p'
420Xpath 'q'
421
422let g:test7_result = g:Xpath
423
424func Test_error_in_script()
425    call assert_equal('abghinoq', g:test7_result)
426endfunc
427
428"-------------------------------------------------------------------------------
429" Test 8:   Aborting and continuing on errors inside functions		    {{{1
430"
431"	    On an error inside a function without the "abort" attribute, the
432"	    script processing continues at the next line (unless the error was
433"	    in a :return command).  On an error inside a function with the
434"	    "abort" attribute, the function is aborted and the script processing
435"	    continues after the function call; the value -1 is returned then.
436"-------------------------------------------------------------------------------
437
438XpathINIT
439
440func T8_F()
441    if 1
442	Xpath 'a'
443	while 1
444	    Xpath 'b'
445	    asdf
446	    Xpath 'c'
447	    asdf | Xpath 'd'
448	    Xpath 'e'
449	    break
450	endwhile
451	Xpath 'f'
452    endif | Xpath 'g'
453    Xpath 'h'
454
455    while 1
456	Xpath 'i'
457	if 1
458	    Xpath 'j'
459	    asdf
460	    Xpath 'k'
461	    asdf | Xpath 'l'
462	    Xpath 'm'
463	endif
464	Xpath 'n'
465	break
466    endwhile | Xpath 'o'
467    Xpath 'p'
468
469    return novar		" returns (default return value 0)
470    Xpath 'q'
471    return 1			" not reached
472endfunc
473
474func T8_G() abort
475    if 1
476	Xpath 'r'
477	while 1
478	    Xpath 's'
479	    asdf		" returns -1
480	    Xpath 't'
481	    break
482	endwhile
483	Xpath 'v'
484    endif | Xpath 'w'
485    Xpath 'x'
486
487    return -4			" not reached
488endfunc
489
490func T8_H() abort
491    while 1
492	Xpath 'A'
493	if 1
494	    Xpath 'B'
495	    asdf		" returns -1
496	    Xpath 'C'
497	endif
498	Xpath 'D'
499	break
500    endwhile | Xpath 'E'
501    Xpath 'F'
502
503    return -4			" not reached
504endfunc
505
506" Aborted functions (T8_G and T8_H) return -1.
507let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H()
508Xpath 'X'
509let g:test8_result = g:Xpath
510
511func Test_error_in_function()
512    call assert_equal(13, g:test8_sum)
513    call assert_equal('abcefghijkmnoprsABX', g:test8_result)
514
515    delfunction T8_F
516    delfunction T8_G
517    delfunction T8_H
518endfunc
519
520
521"-------------------------------------------------------------------------------
522" Test 9:   Continuing after aborted functions				    {{{1
523"
524"	    When a function with the "abort" attribute is aborted due to an
525"	    error, the next function back in the call hierarchy without an
526"	    "abort" attribute continues; the value -1 is returned then.
527"-------------------------------------------------------------------------------
528
529XpathINIT
530
531func F() abort
532    Xpath 'a'
533    let result = G()	" not aborted
534    Xpath 'b'
535    if result != 2
536	Xpath 'c'
537    endif
538    return 1
539endfunc
540
541func G()		" no abort attribute
542    Xpath 'd'
543    if H() != -1	" aborted
544	Xpath 'e'
545    endif
546    Xpath 'f'
547    return 2
548endfunc
549
550func H() abort
551    Xpath 'g'
552    call I()		" aborted
553    Xpath 'h'
554    return 4
555endfunc
556
557func I() abort
558    Xpath 'i'
559    asdf		" error
560    Xpath 'j'
561    return 8
562endfunc
563
564if F() != 1
565    Xpath 'k'
566endif
567
568let g:test9_result = g:Xpath
569
570delfunction F
571delfunction G
572delfunction H
573delfunction I
574
575func Test_func_abort()
576    call assert_equal('adgifb', g:test9_result)
577endfunc
578
579
580"-------------------------------------------------------------------------------
581" Test 10:  :if, :elseif, :while argument parsing			    {{{1
582"
583"	    A '"' or '|' in an argument expression must not be mixed up with
584"	    a comment or a next command after a bar.  Parsing errors should
585"	    be recognized.
586"-------------------------------------------------------------------------------
587
588XpathINIT
589
590func MSG(enr, emsg)
591    let english = v:lang == "C" || v:lang =~ '^[Ee]n'
592    if a:enr == ""
593	Xout "TODO: Add message number for:" a:emsg
594	let v:errmsg = ":" . v:errmsg
595    endif
596    let match = 1
597    if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
598	let match = 0
599	if v:errmsg == ""
600	    Xout "Message missing."
601	else
602	    let v:errmsg = v:errmsg->escape('"')
603	    Xout "Unexpected message:" v:errmsg
604	endif
605    endif
606    return match
607endfunc
608
609if 1 || strlen("\"") | Xpath 'a'
610    Xpath 'b'
611endif
612Xpath 'c'
613
614if 0
615elseif 1 || strlen("\"") | Xpath 'd'
616    Xpath 'e'
617endif
618Xpath 'f'
619
620while 1 || strlen("\"") | Xpath 'g'
621    Xpath 'h'
622    break
623endwhile
624Xpath 'i'
625
626let v:errmsg = ""
627if 1 ||| strlen("\"") | Xpath 'j'
628    Xpath 'k'
629endif
630Xpath 'l'
631if !MSG('E15', "Invalid expression")
632    Xpath 'm'
633endif
634
635let v:errmsg = ""
636if 0
637elseif 1 ||| strlen("\"") | Xpath 'n'
638    Xpath 'o'
639endif
640Xpath 'p'
641if !MSG('E15', "Invalid expression")
642    Xpath 'q'
643endif
644
645let v:errmsg = ""
646while 1 ||| strlen("\"") | Xpath 'r'
647    Xpath 's'
648    break
649endwhile
650Xpath 't'
651if !MSG('E15', "Invalid expression")
652    Xpath 'u'
653endif
654
655let g:test10_result = g:Xpath
656delfunction MSG
657
658func Test_expr_parsing()
659    call assert_equal('abcdefghilpt', g:test10_result)
660endfunc
661
662
663"-------------------------------------------------------------------------------
664" Test 11:  :if, :elseif, :while argument evaluation after abort	    {{{1
665"
666"	    When code is skipped over due to an error, the boolean argument to
667"	    an :if, :elseif, or :while must not be evaluated.
668"-------------------------------------------------------------------------------
669
670XpathINIT
671
672let calls = 0
673
674func P(num)
675    let g:calls = g:calls + a:num   " side effect on call
676    return 0
677endfunc
678
679if 1
680    Xpath 'a'
681    asdf		" error
682    Xpath 'b'
683    if P(1)		" should not be called
684	Xpath 'c'
685    elseif !P(2)	" should not be called
686	Xpath 'd'
687    else
688	Xpath 'e'
689    endif
690    Xpath 'f'
691    while P(4)		" should not be called
692	Xpath 'g'
693    endwhile
694    Xpath 'h'
695endif
696Xpath 'x'
697
698let g:test11_calls = calls
699let g:test11_result = g:Xpath
700
701unlet calls
702delfunction P
703
704func Test_arg_abort()
705    call assert_equal(0, g:test11_calls)
706    call assert_equal('ax', g:test11_result)
707endfunc
708
709
710"-------------------------------------------------------------------------------
711" Test 12:  Expressions in braces in skipped code			    {{{1
712"
713"	    In code skipped over due to an error or inactive conditional,
714"	    an expression in braces as part of a variable or function name
715"	    should not be evaluated.
716"-------------------------------------------------------------------------------
717
718XpathINIT
719
720function! NULL()
721    Xpath 'a'
722    return 0
723endfunction
724
725function! ZERO()
726    Xpath 'b'
727    return 0
728endfunction
729
730function! F0()
731    Xpath 'c'
732endfunction
733
734function! F1(arg)
735    Xpath 'e'
736endfunction
737
738let V0 = 1
739
740Xpath 'f'
741echo 0 ? F{NULL() + V{ZERO()}}() : 1
742
743Xpath 'g'
744if 0
745    Xpath 'h'
746    call F{NULL() + V{ZERO()}}()
747endif
748
749Xpath 'i'
750if 1
751    asdf		" error
752    Xpath 'j'
753    call F1(F{NULL() + V{ZERO()}}())
754endif
755
756Xpath 'k'
757if 1
758    asdf		" error
759    Xpath 'l'
760    call F{NULL() + V{ZERO()}}()
761endif
762
763let g:test12_result = g:Xpath
764
765func Test_braces_skipped()
766    call assert_equal('fgik', g:test12_result)
767endfunc
768
769
770"-------------------------------------------------------------------------------
771" Test 13:  Failure in argument evaluation for :while			    {{{1
772"
773"	    A failure in the expression evaluation for the condition of a :while
774"	    causes the whole :while loop until the matching :endwhile being
775"	    ignored.  Continuation is at the next following line.
776"-------------------------------------------------------------------------------
777
778XpathINIT
779
780Xpath 'a'
781while asdf
782    Xpath 'b'
783    while 1
784	Xpath 'c'
785	break
786    endwhile
787    Xpath 'd'
788    break
789endwhile
790Xpath 'e'
791
792while asdf | Xpath 'f' | endwhile | Xpath 'g'
793Xpath 'h'
794let g:test13_result = g:Xpath
795
796func Test_while_fail()
797    call assert_equal('aeh', g:test13_result)
798endfunc
799
800
801"-------------------------------------------------------------------------------
802" Test 14:  Failure in argument evaluation for :if			    {{{1
803"
804"	    A failure in the expression evaluation for the condition of an :if
805"	    does not cause the corresponding :else or :endif being matched to
806"	    a previous :if/:elseif.  Neither of both branches of the failed :if
807"	    are executed.
808"-------------------------------------------------------------------------------
809
810XpathINIT
811
812function! F()
813    Xpath 'a'
814    let x = 0
815    if x		" false
816	Xpath 'b'
817    elseif !x		" always true
818	Xpath 'c'
819	let x = 1
820	if g:boolvar	" possibly undefined
821	    Xpath 'd'
822	else
823	    Xpath 'e'
824	endif
825	Xpath 'f'
826    elseif x		" never executed
827	Xpath 'g'
828    endif
829    Xpath 'h'
830endfunction
831
832let boolvar = 1
833call F()
834Xpath '-'
835
836unlet boolvar
837call F()
838let g:test14_result = g:Xpath
839
840delfunction F
841
842func Test_if_fail()
843    call assert_equal('acdfh-acfh', g:test14_result)
844endfunc
845
846
847"-------------------------------------------------------------------------------
848" Test 15:  Failure in argument evaluation for :if (bar)		    {{{1
849"
850"	    Like previous test, except that the failing :if ... | ... | :endif
851"	    is in a single line.
852"-------------------------------------------------------------------------------
853
854XpathINIT
855
856function! F()
857    Xpath 'a'
858    let x = 0
859    if x		" false
860	Xpath 'b'
861    elseif !x		" always true
862	Xpath 'c'
863	let x = 1
864	if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif
865	Xpath 'f'
866    elseif x		" never executed
867	Xpath 'g'
868    endif
869    Xpath 'h'
870endfunction
871
872let boolvar = 1
873call F()
874Xpath '-'
875
876unlet boolvar
877call F()
878let g:test15_result = g:Xpath
879
880delfunction F
881
882func Test_if_bar_fail()
883    call assert_equal('acdfh-acfh', g:test15_result)
884endfunc
885
886"-------------------------------------------------------------------------------
887" Test 16:  Double :else or :elseif after :else				    {{{1
888"
889"	    Multiple :elses or an :elseif after an :else are forbidden.
890"-------------------------------------------------------------------------------
891
892func T16_F() abort
893  if 0
894    Xpath 'a'
895  else
896    Xpath 'b'
897  else		" aborts function
898    Xpath 'c'
899  endif
900  Xpath 'd'
901endfunc
902
903func T16_G() abort
904  if 0
905    Xpath 'a'
906  else
907    Xpath 'b'
908  elseif 1		" aborts function
909    Xpath 'c'
910  else
911    Xpath 'd'
912  endif
913  Xpath 'e'
914endfunc
915
916func T16_H() abort
917  if 0
918    Xpath 'a'
919  elseif 0
920    Xpath 'b'
921  else
922    Xpath 'c'
923  else		" aborts function
924    Xpath 'd'
925  endif
926  Xpath 'e'
927endfunc
928
929func T16_I() abort
930  if 0
931    Xpath 'a'
932  elseif 0
933    Xpath 'b'
934  else
935    Xpath 'c'
936  elseif 1		" aborts function
937    Xpath 'd'
938  else
939    Xpath 'e'
940  endif
941  Xpath 'f'
942endfunc
943
944func Test_Multi_Else()
945  XpathINIT
946  try
947    call T16_F()
948  catch /E583:/
949    Xpath 'e'
950  endtry
951  call assert_equal('be', g:Xpath)
952
953  XpathINIT
954  try
955    call T16_G()
956  catch /E584:/
957    Xpath 'f'
958  endtry
959  call assert_equal('bf', g:Xpath)
960
961  XpathINIT
962  try
963    call T16_H()
964  catch /E583:/
965    Xpath 'f'
966  endtry
967  call assert_equal('cf', g:Xpath)
968
969  XpathINIT
970  try
971    call T16_I()
972  catch /E584:/
973    Xpath 'g'
974  endtry
975  call assert_equal('cg', g:Xpath)
976endfunc
977
978"-------------------------------------------------------------------------------
979" Test 17:  Nesting of unmatched :if or :endif inside a :while		    {{{1
980"
981"	    The :while/:endwhile takes precedence in nesting over an unclosed
982"	    :if or an unopened :endif.
983"-------------------------------------------------------------------------------
984
985" While loops inside a function are continued on error.
986func T17_F()
987  let loops = 3
988  while loops > 0
989    let loops -= 1
990    Xpath 'a' . loops
991    if (loops == 1)
992      Xpath 'b' . loops
993      continue
994    elseif (loops == 0)
995      Xpath 'c' . loops
996      break
997    elseif 1
998      Xpath 'd' . loops
999    " endif missing!
1000  endwhile	" :endwhile after :if 1
1001  Xpath 'e'
1002endfunc
1003
1004func T17_G()
1005  let loops = 2
1006  while loops > 0
1007    let loops -= 1
1008    Xpath 'a' . loops
1009    if 0
1010      Xpath 'b' . loops
1011    " endif missing
1012  endwhile	" :endwhile after :if 0
1013endfunc
1014
1015func T17_H()
1016  let loops = 2
1017  while loops > 0
1018    let loops -= 1
1019    Xpath 'a' . loops
1020    " if missing!
1021    endif	" :endif without :if in while
1022    Xpath 'b' . loops
1023  endwhile
1024endfunc
1025
1026" Error continuation outside a function is at the outermost :endwhile or :endif.
1027XpathINIT
1028let v:errmsg = ''
1029let loops = 2
1030while loops > 0
1031    let loops -= 1
1032    Xpath 'a' . loops
1033    if 0
1034	Xpath 'b' . loops
1035    " endif missing! Following :endwhile fails.
1036endwhile | Xpath 'c'
1037Xpath 'd'
1038call assert_match('E171:', v:errmsg)
1039call assert_equal('a1d', g:Xpath)
1040
1041func Test_unmatched_if_in_while()
1042  XpathINIT
1043  call assert_fails('call T17_F()', 'E171:')
1044  call assert_equal('a2d2a1b1a0c0e', g:Xpath)
1045
1046  XpathINIT
1047  call assert_fails('call T17_G()', 'E171:')
1048  call assert_equal('a1a0', g:Xpath)
1049
1050  XpathINIT
1051  call assert_fails('call T17_H()', 'E580:')
1052  call assert_equal('a1b1a0b0', g:Xpath)
1053endfunc
1054
1055"-------------------------------------------------------------------------------
1056" Test 18:  Interrupt (Ctrl-C pressed)					    {{{1
1057"
1058"	    On an interrupt, the script processing is terminated immediately.
1059"-------------------------------------------------------------------------------
1060
1061func Test_interrupt_while_if()
1062  let test =<< trim [CODE]
1063    try
1064      if 1
1065        Xpath 'a'
1066        while 1
1067          Xpath 'b'
1068          if 1
1069            Xpath 'c'
1070            call interrupt()
1071            call assert_report('should not get here')
1072            break
1073            finish
1074          endif | call assert_report('should not get here')
1075          call assert_report('should not get here')
1076        endwhile | call assert_report('should not get here')
1077        call assert_report('should not get here')
1078      endif | call assert_report('should not get here')
1079      call assert_report('should not get here')
1080    catch /^Vim:Interrupt$/
1081      Xpath 'd'
1082    endtry | Xpath 'e'
1083    Xpath 'f'
1084  [CODE]
1085  let verify =<< trim [CODE]
1086    call assert_equal('abcdef', g:Xpath)
1087  [CODE]
1088  call RunInNewVim(test, verify)
1089endfunc
1090
1091func Test_interrupt_try()
1092  let test =<< trim [CODE]
1093    try
1094      try
1095        Xpath 'a'
1096        call interrupt()
1097        call assert_report('should not get here')
1098      endtry | call assert_report('should not get here')
1099      call assert_report('should not get here')
1100    catch /^Vim:Interrupt$/
1101      Xpath 'b'
1102    endtry | Xpath 'c'
1103    Xpath 'd'
1104  [CODE]
1105  let verify =<< trim [CODE]
1106    call assert_equal('abcd', g:Xpath)
1107  [CODE]
1108  call RunInNewVim(test, verify)
1109endfunc
1110
1111func Test_interrupt_func_while_if()
1112  let test =<< trim [CODE]
1113    func F()
1114      if 1
1115        Xpath 'a'
1116        while 1
1117          Xpath 'b'
1118          if 1
1119            Xpath 'c'
1120            call interrupt()
1121            call assert_report('should not get here')
1122            break
1123            return
1124          endif | call assert_report('should not get here')
1125          call assert_report('should not get here')
1126        endwhile | call assert_report('should not get here')
1127        call assert_report('should not get here')
1128      endif | call assert_report('should not get here')
1129      call assert_report('should not get here')
1130    endfunc
1131
1132    Xpath 'd'
1133    try
1134      call F() | call assert_report('should not get here')
1135    catch /^Vim:Interrupt$/
1136      Xpath 'e'
1137    endtry | Xpath 'f'
1138    Xpath 'g'
1139  [CODE]
1140  let verify =<< trim [CODE]
1141    call assert_equal('dabcefg', g:Xpath)
1142  [CODE]
1143  call RunInNewVim(test, verify)
1144endfunc
1145
1146func Test_interrupt_func_try()
1147  let test =<< trim [CODE]
1148    func G()
1149      try
1150        Xpath 'a'
1151        call interrupt()
1152        call assert_report('should not get here')
1153      endtry | call assert_report('should not get here')
1154      call assert_report('should not get here')
1155    endfunc
1156
1157    Xpath 'b'
1158    try
1159      call G() | call assert_report('should not get here')
1160    catch /^Vim:Interrupt$/
1161      Xpath 'c'
1162    endtry | Xpath 'd'
1163    Xpath 'e'
1164  [CODE]
1165  let verify =<< trim [CODE]
1166    call assert_equal('bacde', g:Xpath)
1167  [CODE]
1168  call RunInNewVim(test, verify)
1169endfunc
1170
1171"-------------------------------------------------------------------------------
1172" Test 19:  Aborting on errors inside :try/:endtry			    {{{1
1173"
1174"	    An error in a command dynamically enclosed in a :try/:endtry region
1175"	    aborts script processing immediately.  It does not matter whether
1176"	    the failing command is outside or inside a function and whether a
1177"	    function has an "abort" attribute.
1178"-------------------------------------------------------------------------------
1179
1180func Test_try_error_abort_1()
1181  let test =<< trim [CODE]
1182    func F() abort
1183      Xpath 'a'
1184      asdf
1185      call assert_report('should not get here')
1186    endfunc
1187
1188    try
1189      Xpath 'b'
1190      call F()
1191      call assert_report('should not get here')
1192    endtry | call assert_report('should not get here')
1193    call assert_report('should not get here')
1194  [CODE]
1195  let verify =<< trim [CODE]
1196    call assert_equal('ba', g:Xpath)
1197  [CODE]
1198  call RunInNewVim(test, verify)
1199endfunc
1200
1201func Test_try_error_abort_2()
1202  let test =<< trim [CODE]
1203    func G()
1204      Xpath 'a'
1205      asdf
1206      call assert_report('should not get here')
1207    endfunc
1208
1209    try
1210      Xpath 'b'
1211      call G()
1212      call assert_report('should not get here')
1213    endtry | call assert_report('should not get here')
1214    call assert_report('should not get here')
1215  [CODE]
1216  let verify =<< trim [CODE]
1217    call assert_equal('ba', g:Xpath)
1218  [CODE]
1219  call RunInNewVim(test, verify)
1220endfunc
1221
1222func Test_try_error_abort_3()
1223  let test =<< trim [CODE]
1224    try
1225      Xpath 'a'
1226      asdf
1227      call assert_report('should not get here')
1228    endtry | call assert_report('should not get here')
1229    call assert_report('should not get here')
1230  [CODE]
1231  let verify =<< trim [CODE]
1232    call assert_equal('a', g:Xpath)
1233  [CODE]
1234  call RunInNewVim(test, verify)
1235endfunc
1236
1237func Test_try_error_abort_4()
1238  let test =<< trim [CODE]
1239    if 1
1240      try
1241        Xpath 'a'
1242        asdf
1243        call assert_report('should not get here')
1244      endtry | call assert_report('should not get here')
1245    endif | call assert_report('should not get here')
1246    call assert_report('should not get here')
1247  [CODE]
1248  let verify =<< trim [CODE]
1249    call assert_equal('a', g:Xpath)
1250  [CODE]
1251  call RunInNewVim(test, verify)
1252endfunc
1253
1254func Test_try_error_abort_5()
1255  let test =<< trim [CODE]
1256    let p = 1
1257    while p
1258      let p = 0
1259      try
1260        Xpath 'a'
1261        asdf
1262        call assert_report('should not get here')
1263      endtry | call assert_report('should not get here')
1264    endwhile | call assert_report('should not get here')
1265    call assert_report('should not get here')
1266  [CODE]
1267  let verify =<< trim [CODE]
1268    call assert_equal('a', g:Xpath)
1269  [CODE]
1270  call RunInNewVim(test, verify)
1271endfunc
1272
1273func Test_try_error_abort_6()
1274  let test =<< trim [CODE]
1275    let p = 1
1276    Xpath 'a'
1277    while p
1278      Xpath 'b'
1279      let p = 0
1280      try
1281        Xpath 'c'
1282    endwhile | call assert_report('should not get here')
1283    call assert_report('should not get here')
1284  [CODE]
1285  let verify =<< trim [CODE]
1286    call assert_equal('abc', g:Xpath)
1287  [CODE]
1288  call RunInNewVim(test, verify)
1289endfunc
1290
1291"-------------------------------------------------------------------------------
1292" Test 20:  Aborting on errors after :try/:endtry			    {{{1
1293"
1294"	    When an error occurs after the last active :try/:endtry region has
1295"	    been left, termination behavior is as if no :try/:endtry has been
1296"	    seen.
1297"-------------------------------------------------------------------------------
1298
1299func Test_error_after_try_1()
1300  let test =<< trim [CODE]
1301    let p = 1
1302    while p
1303      let p = 0
1304      Xpath 'a'
1305      try
1306        Xpath 'b'
1307      endtry
1308      asdf
1309      call assert_report('should not get here')
1310    endwhile | call assert_report('should not get here')
1311    Xpath 'c'
1312  [CODE]
1313  let verify =<< trim [CODE]
1314    call assert_equal('abc', g:Xpath)
1315  [CODE]
1316  call RunInNewVim(test, verify)
1317endfunc
1318
1319func Test_error_after_try_2()
1320  let test =<< trim [CODE]
1321    while 1
1322      try
1323        Xpath 'a'
1324        break
1325        call assert_report('should not get here')
1326      endtry
1327    endwhile
1328    Xpath 'b'
1329    asdf
1330    Xpath 'c'
1331  [CODE]
1332  let verify =<< trim [CODE]
1333    call assert_equal('abc', g:Xpath)
1334  [CODE]
1335  call RunInNewVim(test, verify)
1336endfunc
1337
1338func Test_error_after_try_3()
1339  let test =<< trim [CODE]
1340    while 1
1341      try
1342        Xpath 'a'
1343        break
1344        call assert_report('should not get here')
1345      finally
1346        Xpath 'b'
1347      endtry
1348    endwhile
1349    Xpath 'c'
1350    asdf
1351    Xpath 'd'
1352  [CODE]
1353  let verify =<< trim [CODE]
1354    call assert_equal('abcd', g:Xpath)
1355  [CODE]
1356  call RunInNewVim(test, verify)
1357endfunc
1358
1359func Test_error_after_try_4()
1360  let test =<< trim [CODE]
1361    while 1
1362      try
1363        Xpath 'a'
1364      finally
1365        Xpath 'b'
1366        break
1367        call assert_report('should not get here')
1368      endtry
1369    endwhile
1370    Xpath 'c'
1371    asdf
1372    Xpath 'd'
1373  [CODE]
1374  let verify =<< trim [CODE]
1375    call assert_equal('abcd', g:Xpath)
1376  [CODE]
1377  call RunInNewVim(test, verify)
1378endfunc
1379
1380func Test_error_after_try_5()
1381  let test =<< trim [CODE]
1382    let p = 1
1383    while p
1384      let p = 0
1385      try
1386        Xpath 'a'
1387        continue
1388        call assert_report('should not get here')
1389      endtry
1390    endwhile
1391    Xpath 'b'
1392    asdf
1393    Xpath 'c'
1394  [CODE]
1395  let verify =<< trim [CODE]
1396    call assert_equal('abc', g:Xpath)
1397  [CODE]
1398  call RunInNewVim(test, verify)
1399endfunc
1400
1401func Test_error_after_try_6()
1402  let test =<< trim [CODE]
1403    let p = 1
1404    while p
1405      let p = 0
1406      try
1407        Xpath 'a'
1408        continue
1409        call assert_report('should not get here')
1410      finally
1411        Xpath 'b'
1412      endtry
1413    endwhile
1414    Xpath 'c'
1415    asdf
1416    Xpath 'd'
1417  [CODE]
1418  let verify =<< trim [CODE]
1419    call assert_equal('abcd', g:Xpath)
1420  [CODE]
1421  call RunInNewVim(test, verify)
1422endfunc
1423
1424func Test_error_after_try_7()
1425  let test =<< trim [CODE]
1426    let p = 1
1427    while p
1428      let p = 0
1429      try
1430        Xpath 'a'
1431      finally
1432        Xpath 'b'
1433        continue
1434        call assert_report('should not get here')
1435      endtry
1436    endwhile
1437    Xpath 'c'
1438    asdf
1439    Xpath 'd'
1440  [CODE]
1441  let verify =<< trim [CODE]
1442    call assert_equal('abcd', g:Xpath)
1443  [CODE]
1444  call RunInNewVim(test, verify)
1445endfunc
1446
1447"-------------------------------------------------------------------------------
1448" Test 21:  :finally for :try after :continue/:break/:return/:finish	    {{{1
1449"
1450"	    If a :try conditional stays inactive due to a preceding :continue,
1451"	    :break, :return, or :finish, its :finally clause should not be
1452"	    executed.
1453"-------------------------------------------------------------------------------
1454
1455func Test_finally_after_loop_ctrl_statement()
1456  let test =<< trim [CODE]
1457    func F()
1458      let loops = 2
1459      while loops > 0
1460        XloopNEXT
1461        let loops = loops - 1
1462        try
1463          if loops == 1
1464            Xloop 'a'
1465            continue
1466            call assert_report('should not get here')
1467          elseif loops == 0
1468            Xloop 'b'
1469            break
1470            call assert_report('should not get here')
1471          endif
1472
1473          try		" inactive
1474            call assert_report('should not get here')
1475          finally
1476            call assert_report('should not get here')
1477          endtry
1478        finally
1479          Xloop 'c'
1480        endtry
1481        call assert_report('should not get here')
1482      endwhile
1483
1484      try
1485        Xpath 'd'
1486        return
1487        call assert_report('should not get here')
1488        try		    " inactive
1489          call assert_report('should not get here')
1490        finally
1491          call assert_report('should not get here')
1492        endtry
1493      finally
1494        Xpath 'e'
1495      endtry
1496      call assert_report('should not get here')
1497    endfunc
1498
1499    try
1500      Xpath 'f'
1501      call F()
1502      Xpath 'g'
1503      finish
1504      call assert_report('should not get here')
1505      try		" inactive
1506        call assert_report('should not get here')
1507      finally
1508        call assert_report('should not get here')
1509      endtry
1510    finally
1511      Xpath 'h'
1512    endtry
1513    call assert_report('should not get here')
1514  [CODE]
1515  let verify =<< trim [CODE]
1516    call assert_equal('fa2c2b3c3degh', g:Xpath)
1517  [CODE]
1518  call RunInNewVim(test, verify)
1519endfunc
1520
1521"-------------------------------------------------------------------------------
1522" Test 22:  :finally for a :try after an error/interrupt/:throw		    {{{1
1523"
1524"	    If a :try conditional stays inactive due to a preceding error or
1525"	    interrupt or :throw, its :finally clause should not be executed.
1526"-------------------------------------------------------------------------------
1527
1528func Test_finally_after_error_in_func()
1529  let test =<< trim [CODE]
1530    func Error()
1531      try
1532        Xpath 'b'
1533        asdf    " aborting error, triggering error exception
1534        call assert_report('should not get here')
1535      endtry
1536      call assert_report('should not get here')
1537    endfunc
1538
1539    Xpath 'a'
1540    call Error()
1541    call assert_report('should not get here')
1542
1543    if 1	" not active due to error
1544      try	" not active since :if inactive
1545        call assert_report('should not get here')
1546      finally
1547        call assert_report('should not get here')
1548      endtry
1549    endif
1550
1551    try		" not active due to error
1552      call assert_report('should not get here')
1553    finally
1554      call assert_report('should not get here')
1555    endtry
1556  [CODE]
1557  let verify =<< trim [CODE]
1558    call assert_equal('ab', g:Xpath)
1559  [CODE]
1560  call RunInNewVim(test, verify)
1561endfunc
1562
1563func Test_finally_after_interrupt()
1564  let test =<< trim [CODE]
1565    func Interrupt()
1566      try
1567        Xpath 'a'
1568        call interrupt()            " triggering interrupt exception
1569        call assert_report('should not get here')
1570      endtry
1571    endfunc
1572
1573    Xpath 'b'
1574    try
1575      call Interrupt()
1576    catch /^Vim:Interrupt$/
1577      Xpath 'c'
1578      finish
1579    endtry
1580    call assert_report('should not get here')
1581
1582    if 1	" not active due to interrupt
1583      try	" not active since :if inactive
1584        call assert_report('should not get here')
1585      finally
1586        call assert_report('should not get here')
1587      endtry
1588    endif
1589
1590    try		" not active due to interrupt
1591      call assert_report('should not get here')
1592    finally
1593      call assert_report('should not get here')
1594    endtry
1595  [CODE]
1596  let verify =<< trim [CODE]
1597    call assert_equal('bac', g:Xpath)
1598  [CODE]
1599  call RunInNewVim(test, verify)
1600endfunc
1601
1602func Test_finally_after_throw()
1603  let test =<< trim [CODE]
1604    func Throw()
1605      Xpath 'a'
1606      throw 'xyz'
1607    endfunc
1608
1609    Xpath 'b'
1610    call Throw()
1611    call assert_report('should not get here')
1612
1613    if 1	" not active due to :throw
1614      try	" not active since :if inactive
1615        call assert_report('should not get here')
1616      finally
1617        call assert_report('should not get here')
1618      endtry
1619    endif
1620
1621    try		" not active due to :throw
1622      call assert_report('should not get here')
1623    finally
1624      call assert_report('should not get here')
1625    endtry
1626  [CODE]
1627  let verify =<< trim [CODE]
1628    call assert_equal('ba', g:Xpath)
1629  [CODE]
1630  call RunInNewVim(test, verify)
1631endfunc
1632
1633"-------------------------------------------------------------------------------
1634" Test 23:  :catch clauses for a :try after a :throw			    {{{1
1635"
1636"	    If a :try conditional stays inactive due to a preceding :throw,
1637"	    none of its :catch clauses should be executed.
1638"-------------------------------------------------------------------------------
1639
1640func Test_catch_after_throw()
1641  let test =<< trim [CODE]
1642    try
1643      Xpath 'a'
1644      throw "xyz"
1645      call assert_report('should not get here')
1646
1647      if 1	" not active due to :throw
1648        try	" not active since :if inactive
1649          call assert_report('should not get here')
1650        catch /xyz/
1651          call assert_report('should not get here')
1652        endtry
1653      endif
1654    catch /xyz/
1655      Xpath 'b'
1656    endtry
1657
1658    Xpath 'c'
1659    throw "abc"
1660    call assert_report('should not get here')
1661
1662    try		" not active due to :throw
1663      call assert_report('should not get here')
1664    catch /abc/
1665      call assert_report('should not get here')
1666    endtry
1667  [CODE]
1668  let verify =<< trim [CODE]
1669    call assert_equal('abc', g:Xpath)
1670  [CODE]
1671  call RunInNewVim(test, verify)
1672endfunc
1673
1674"-------------------------------------------------------------------------------
1675" Test 24:  :endtry for a :try after a :throw				    {{{1
1676"
1677"	    If a :try conditional stays inactive due to a preceding :throw,
1678"	    its :endtry should not rethrow the exception to the next surrounding
1679"	    active :try conditional.
1680"-------------------------------------------------------------------------------
1681
1682func Test_endtry_after_throw()
1683  let test =<< trim [CODE]
1684    try			" try 1
1685      try		" try 2
1686        Xpath 'a'
1687        throw "xyz"	" makes try 2 inactive
1688        call assert_report('should not get here')
1689
1690        try		" try 3
1691          call assert_report('should not get here')
1692        endtry	" no rethrow to try 1
1693      catch /xyz/	" should catch although try 2 inactive
1694        Xpath 'b'
1695      endtry
1696    catch /xyz/		" try 1 active, but exception already caught
1697      call assert_report('should not get here')
1698    endtry
1699    Xpath 'c'
1700  [CODE]
1701  let verify =<< trim [CODE]
1702    call assert_equal('abc', g:Xpath)
1703  [CODE]
1704  call RunInNewVim(test, verify)
1705endfunc
1706
1707"-------------------------------------------------------------------------------
1708" Test 27:  Executing :finally clauses after :return			    {{{1
1709"
1710"	    For a :return command dynamically enclosed in a :try/:endtry region,
1711"	    :finally clauses are executed and the called function is ended.
1712"-------------------------------------------------------------------------------
1713
1714func T27_F()
1715  try
1716    Xpath 'a'
1717    try
1718      Xpath 'b'
1719      return
1720      call assert_report('should not get here')
1721    finally
1722      Xpath 'c'
1723    endtry
1724    Xpath 'd'
1725  finally
1726    Xpath 'e'
1727  endtry
1728  call assert_report('should not get here')
1729endfunc
1730
1731func T27_G()
1732  try
1733    Xpath 'f'
1734    return
1735    call assert_report('should not get here')
1736  finally
1737    Xpath 'g'
1738    call T27_F()
1739    Xpath 'h'
1740  endtry
1741  call assert_report('should not get here')
1742endfunc
1743
1744func T27_H()
1745  try
1746    Xpath 'i'
1747    call T27_G()
1748    Xpath 'j'
1749  finally
1750    Xpath 'k'
1751    return
1752    call assert_report('should not get here')
1753  endtry
1754  call assert_report('should not get here')
1755endfunction
1756
1757func Test_finally_after_return()
1758  XpathINIT
1759  try
1760      Xpath 'l'
1761      call T27_H()
1762      Xpath 'm'
1763  finally
1764      Xpath 'n'
1765  endtry
1766  call assert_equal('lifgabcehjkmn', g:Xpath)
1767endfunc
1768
1769"-------------------------------------------------------------------------------
1770" Test 28:  Executing :finally clauses after :finish			    {{{1
1771"
1772"	    For a :finish command dynamically enclosed in a :try/:endtry region,
1773"	    :finally clauses are executed and the sourced file is finished.
1774"
1775"	    This test executes the bodies of the functions F, G, and H from the
1776"	    previous test as script files (:return replaced by :finish).
1777"-------------------------------------------------------------------------------
1778
1779func Test_finally_after_finish()
1780  XpathINIT
1781
1782  let scriptF = MakeScript("T27_F")
1783  let scriptG = MakeScript("T27_G", scriptF)
1784  let scriptH = MakeScript("T27_H", scriptG)
1785
1786  try
1787    Xpath 'A'
1788    exec "source" scriptH
1789    Xpath 'B'
1790  finally
1791    Xpath 'C'
1792  endtry
1793  Xpath 'D'
1794  call assert_equal('AifgabcehjkBCD', g:Xpath)
1795  call delete(scriptF)
1796  call delete(scriptG)
1797  call delete(scriptH)
1798endfunc
1799
1800"-------------------------------------------------------------------------------
1801" Test 29:  Executing :finally clauses on errors			    {{{1
1802"
1803"	    After an error in a command dynamically enclosed in a :try/:endtry
1804"	    region, :finally clauses are executed and the script processing is
1805"	    terminated.
1806"-------------------------------------------------------------------------------
1807
1808func Test_finally_after_error_1()
1809  let test =<< trim [CODE]
1810    func F()
1811      while 1
1812        try
1813          Xpath 'a'
1814          while 1
1815            try
1816              Xpath 'b'
1817              asdf	    " error
1818              call assert_report('should not get here')
1819            finally
1820              Xpath 'c'
1821            endtry | call assert_report('should not get here')
1822            call assert_report('should not get here')
1823            break
1824          endwhile
1825          call assert_report('should not get here')
1826        finally
1827          Xpath 'd'
1828        endtry | call assert_report('should not get here')
1829        call assert_report('should not get here')
1830        break
1831      endwhile
1832      call assert_report('should not get here')
1833    endfunc
1834
1835    while 1
1836      try
1837        Xpath 'e'
1838        while 1
1839          call F()
1840          call assert_report('should not get here')
1841          break
1842        endwhile  | call assert_report('should not get here')
1843        call assert_report('should not get here')
1844      finally
1845        Xpath 'f'
1846      endtry | call assert_report('should not get here')
1847    endwhile | call assert_report('should not get here')
1848    call assert_report('should not get here')
1849  [CODE]
1850  let verify =<< trim [CODE]
1851    call assert_equal('eabcdf', g:Xpath)
1852  [CODE]
1853  call RunInNewVim(test, verify)
1854endfunc
1855
1856func Test_finally_after_error_2()
1857  let test =<< trim [CODE]
1858    func G() abort
1859      if 1
1860        try
1861          Xpath 'a'
1862          asdf	    " error
1863          call assert_report('should not get here')
1864        finally
1865          Xpath 'b'
1866        endtry | Xpath 'c'
1867      endif | Xpath 'd'
1868      call assert_report('should not get here')
1869    endfunc
1870
1871    if 1
1872      try
1873        Xpath 'e'
1874        call G()
1875        call assert_report('should not get here')
1876      finally
1877        Xpath 'f'
1878      endtry | call assert_report('should not get here')
1879    endif | call assert_report('should not get here')
1880    call assert_report('should not get here')
1881  [CODE]
1882  let verify =<< trim [CODE]
1883    call assert_equal('eabf', g:Xpath)
1884  [CODE]
1885  call RunInNewVim(test, verify)
1886endfunc
1887
1888"-------------------------------------------------------------------------------
1889" Test 30:  Executing :finally clauses on interrupt			    {{{1
1890"
1891"	    After an interrupt in a command dynamically enclosed in
1892"	    a :try/:endtry region, :finally clauses are executed and the
1893"	    script processing is terminated.
1894"-------------------------------------------------------------------------------
1895
1896func Test_finally_on_interrupt()
1897  let test =<< trim [CODE]
1898    func F()
1899      try
1900        Xloop 'a'
1901        call interrupt()
1902        call assert_report('should not get here')
1903      finally
1904        Xloop 'b'
1905      endtry
1906      call assert_report('should not get here')
1907    endfunc
1908
1909    try
1910      try
1911        Xpath 'c'
1912        try
1913          Xpath 'd'
1914          call interrupt()
1915          call assert_report('should not get here')
1916        finally
1917          Xpath 'e'
1918          try
1919            Xpath 'f'
1920            try
1921              Xpath 'g'
1922            finally
1923              Xpath 'h'
1924              try
1925                Xpath 'i'
1926                call interrupt()
1927                call assert_report('should not get here')
1928              endtry
1929              call assert_report('should not get here')
1930            endtry
1931            call assert_report('should not get here')
1932          endtry
1933          call assert_report('should not get here')
1934        endtry
1935        call assert_report('should not get here')
1936      finally
1937        Xpath 'j'
1938        try
1939          Xpath 'k'
1940          call F()
1941          call assert_report('should not get here')
1942        finally
1943          Xpath 'l'
1944          try
1945            Xpath 'm'
1946            XloopNEXT
1947            ExecAsScript F
1948            call assert_report('should not get here')
1949          finally
1950            Xpath 'n'
1951          endtry
1952          call assert_report('should not get here')
1953        endtry
1954        call assert_report('should not get here')
1955      endtry
1956      call assert_report('should not get here')
1957    catch /^Vim:Interrupt$/
1958      Xpath 'o'
1959    endtry
1960  [CODE]
1961  let verify =<< trim [CODE]
1962    call assert_equal('cdefghijka1b1lma2b2no', g:Xpath)
1963  [CODE]
1964  call RunInNewVim(test, verify)
1965endfunc
1966
1967"-------------------------------------------------------------------------------
1968" Test 31:  Executing :finally clauses after :throw			    {{{1
1969"
1970"	    After a :throw dynamically enclosed in a :try/:endtry region,
1971"	    :finally clauses are executed and the script processing is
1972"	    terminated.
1973"-------------------------------------------------------------------------------
1974
1975func Test_finally_after_throw_2()
1976  let test =<< trim [CODE]
1977    func F()
1978      try
1979        Xloop 'a'
1980        throw "exception"
1981        call assert_report('should not get here')
1982      finally
1983        Xloop 'b'
1984      endtry
1985      call assert_report('should not get here')
1986    endfunc
1987
1988    try
1989      Xpath 'c'
1990      try
1991        Xpath 'd'
1992        throw "exception"
1993        call assert_report('should not get here')
1994      finally
1995        Xpath 'e'
1996        try
1997          Xpath 'f'
1998          try
1999            Xpath 'g'
2000          finally
2001            Xpath 'h'
2002            try
2003              Xpath 'i'
2004              throw "exception"
2005              call assert_report('should not get here')
2006            endtry
2007            call assert_report('should not get here')
2008          endtry
2009          call assert_report('should not get here')
2010        endtry
2011        call assert_report('should not get here')
2012      endtry
2013      call assert_report('should not get here')
2014    finally
2015      Xpath 'j'
2016      try
2017        Xpath 'k'
2018        call F()
2019        call assert_report('should not get here')
2020      finally
2021        Xpath 'l'
2022        try
2023          Xpath 'm'
2024          XloopNEXT
2025          ExecAsScript F
2026          call assert_report('should not get here')
2027        finally
2028          Xpath 'n'
2029        endtry
2030        call assert_report('should not get here')
2031      endtry
2032      call assert_report('should not get here')
2033    endtry
2034    call assert_report('should not get here')
2035  [CODE]
2036  let verify =<< trim [CODE]
2037    call assert_equal('cdefghijka1b1lma2b2n', g:Xpath)
2038  [CODE]
2039  call RunInNewVim(test, verify)
2040endfunc
2041
2042"-------------------------------------------------------------------------------
2043" Test 34:  :finally reason discarded by :continue			    {{{1
2044"
2045"	    When a :finally clause is executed due to a :continue, :break,
2046"	    :return, :finish, error, interrupt or :throw, the jump reason is
2047"	    discarded by a :continue in the finally clause.
2048"-------------------------------------------------------------------------------
2049
2050func Test_finally_after_continue()
2051  let test =<< trim [CODE]
2052    func C(jump)
2053      XloopNEXT
2054      let loop = 0
2055      while loop < 2
2056        let loop = loop + 1
2057        if loop == 1
2058          try
2059            if a:jump == "continue"
2060              continue
2061            elseif a:jump == "break"
2062              break
2063            elseif a:jump == "return" || a:jump == "finish"
2064              return
2065            elseif a:jump == "error"
2066              asdf
2067            elseif a:jump == "interrupt"
2068              call interrupt()
2069              let dummy = 0
2070            elseif a:jump == "throw"
2071              throw "abc"
2072            endif
2073          finally
2074            continue	" discards jump that caused the :finally
2075            call assert_report('should not get here')
2076          endtry
2077          call assert_report('should not get here')
2078        elseif loop == 2
2079          Xloop 'a'
2080        endif
2081      endwhile
2082    endfunc
2083
2084    call C("continue")
2085    Xpath 'b'
2086    call C("break")
2087    Xpath 'c'
2088    call C("return")
2089    Xpath 'd'
2090    let g:jump = "finish"
2091    ExecAsScript C
2092    unlet g:jump
2093    Xpath 'e'
2094    try
2095      call C("error")
2096      Xpath 'f'
2097    finally
2098      Xpath 'g'
2099      try
2100        call C("interrupt")
2101        Xpath 'h'
2102      finally
2103        Xpath 'i'
2104        call C("throw")
2105        Xpath 'j'
2106      endtry
2107    endtry
2108    Xpath 'k'
2109  [CODE]
2110  let verify =<< trim [CODE]
2111    call assert_equal('a2ba3ca4da5ea6fga7hia8jk', g:Xpath)
2112  [CODE]
2113  call RunInNewVim(test, verify)
2114endfunc
2115
2116"-------------------------------------------------------------------------------
2117" Test 35:  :finally reason discarded by :break				    {{{1
2118"
2119"	    When a :finally clause is executed due to a :continue, :break,
2120"	    :return, :finish, error, interrupt or :throw, the jump reason is
2121"	    discarded by a :break in the finally clause.
2122"-------------------------------------------------------------------------------
2123
2124func Test_finally_discard_by_break()
2125  let test =<< trim [CODE]
2126    func B(jump)
2127      XloopNEXT
2128      let loop = 0
2129      while loop < 2
2130        let loop = loop + 1
2131        if loop == 1
2132          try
2133            if a:jump == "continue"
2134              continue
2135            elseif a:jump == "break"
2136              break
2137            elseif a:jump == "return" || a:jump == "finish"
2138              return
2139            elseif a:jump == "error"
2140              asdf
2141            elseif a:jump == "interrupt"
2142              call interrupt()
2143              let dummy = 0
2144            elseif a:jump == "throw"
2145              throw "abc"
2146            endif
2147          finally
2148            break	" discards jump that caused the :finally
2149            call assert_report('should not get here')
2150          endtry
2151        elseif loop == 2
2152          call assert_report('should not get here')
2153        endif
2154      endwhile
2155      Xloop 'a'
2156    endfunc
2157
2158    call B("continue")
2159    Xpath 'b'
2160    call B("break")
2161    Xpath 'c'
2162    call B("return")
2163    Xpath 'd'
2164    let g:jump = "finish"
2165    ExecAsScript B
2166    unlet g:jump
2167    Xpath 'e'
2168    try
2169      call B("error")
2170      Xpath 'f'
2171    finally
2172      Xpath 'g'
2173      try
2174        call B("interrupt")
2175        Xpath 'h'
2176      finally
2177        Xpath 'i'
2178        call B("throw")
2179        Xpath 'j'
2180      endtry
2181    endtry
2182    Xpath 'k'
2183  [CODE]
2184  let verify =<< trim [CODE]
2185    call assert_equal('a2ba3ca4da5ea6fga7hia8jk', g:Xpath)
2186  [CODE]
2187  call RunInNewVim(test, verify)
2188endfunc
2189
2190"-------------------------------------------------------------------------------
2191" Test 36:  :finally reason discarded by :return			    {{{1
2192"
2193"	    When a :finally clause is executed due to a :continue, :break,
2194"	    :return, :finish, error, interrupt or :throw, the jump reason is
2195"	    discarded by a :return in the finally clause.
2196"-------------------------------------------------------------------------------
2197
2198func Test_finally_discard_by_return()
2199  let test =<< trim [CODE]
2200    func R(jump, retval) abort
2201      let loop = 0
2202      while loop < 2
2203        let loop = loop + 1
2204        if loop == 1
2205          try
2206            if a:jump == "continue"
2207              continue
2208            elseif a:jump == "break"
2209              break
2210            elseif a:jump == "return"
2211              return
2212            elseif a:jump == "error"
2213              asdf
2214            elseif a:jump == "interrupt"
2215              call interrupt()
2216              let dummy = 0
2217            elseif a:jump == "throw"
2218              throw "abc"
2219            endif
2220          finally
2221            return a:retval	" discards jump that caused the :finally
2222            call assert_report('should not get here')
2223          endtry
2224        elseif loop == 2
2225          call assert_report('should not get here')
2226        endif
2227      endwhile
2228      call assert_report('should not get here')
2229    endfunc
2230
2231    let sum =  -R("continue", -8)
2232    Xpath 'a'
2233    let sum = sum - R("break", -16)
2234    Xpath 'b'
2235    let sum = sum - R("return", -32)
2236    Xpath 'c'
2237    try
2238      let sum = sum - R("error", -64)
2239      Xpath 'd'
2240    finally
2241      Xpath 'e'
2242      try
2243        let sum = sum - R("interrupt", -128)
2244        Xpath 'f'
2245      finally
2246        Xpath 'g'
2247        let sum = sum - R("throw", -256)
2248        Xpath 'h'
2249      endtry
2250    endtry
2251    Xpath 'i'
2252
2253    let expected = 8 + 16 + 32 + 64 + 128 + 256
2254    call assert_equal(sum, expected)
2255  [CODE]
2256  let verify =<< trim [CODE]
2257    call assert_equal('abcdefghi', g:Xpath)
2258  [CODE]
2259  call RunInNewVim(test, verify)
2260endfunc
2261
2262"-------------------------------------------------------------------------------
2263" Test 37:  :finally reason discarded by :finish			    {{{1
2264"
2265"	    When a :finally clause is executed due to a :continue, :break,
2266"	    :return, :finish, error, interrupt or :throw, the jump reason is
2267"	    discarded by a :finish in the finally clause.
2268"-------------------------------------------------------------------------------
2269
2270func Test_finally_discard_by_finish()
2271  let test =<< trim [CODE]
2272    func F(jump)	" not executed as function, transformed to a script
2273      let loop = 0
2274      while loop < 2
2275        let loop = loop + 1
2276        if loop == 1
2277          try
2278            if a:jump == "continue"
2279              continue
2280            elseif a:jump == "break"
2281              break
2282            elseif a:jump == "finish"
2283              finish
2284            elseif a:jump == "error"
2285              asdf
2286            elseif a:jump == "interrupt"
2287              call interrupt()
2288              let dummy = 0
2289            elseif a:jump == "throw"
2290              throw "abc"
2291            endif
2292          finally
2293            finish	" discards jump that caused the :finally
2294            call assert_report('should not get here')
2295          endtry
2296        elseif loop == 2
2297          call assert_report('should not get here')
2298        endif
2299      endwhile
2300      call assert_report('should not get here')
2301    endfunc
2302
2303    let scriptF = MakeScript("F")
2304    delfunction F
2305
2306    let g:jump = "continue"
2307    exec "source" scriptF
2308    Xpath 'a'
2309    let g:jump = "break"
2310    exec "source" scriptF
2311    Xpath 'b'
2312    let g:jump = "finish"
2313    exec "source" scriptF
2314    Xpath 'c'
2315    try
2316      let g:jump = "error"
2317      exec "source" scriptF
2318      Xpath 'd'
2319    finally
2320      Xpath 'e'
2321      try
2322        let g:jump = "interrupt"
2323        exec "source" scriptF
2324        Xpath 'f'
2325      finally
2326        Xpath 'g'
2327        try
2328          let g:jump = "throw"
2329          exec "source" scriptF
2330          Xpath 'h'
2331        finally
2332          Xpath 'i'
2333        endtry
2334      endtry
2335    endtry
2336    unlet g:jump
2337    call delete(scriptF)
2338  [CODE]
2339  let verify =<< trim [CODE]
2340    call assert_equal('abcdefghi', g:Xpath)
2341  [CODE]
2342  call RunInNewVim(test, verify)
2343endfunc
2344
2345"-------------------------------------------------------------------------------
2346" Test 38:  :finally reason discarded by an error			    {{{1
2347"
2348"	    When a :finally clause is executed due to a :continue, :break,
2349"	    :return, :finish, error, interrupt or :throw, the jump reason is
2350"	    discarded by an error in the finally clause.
2351"-------------------------------------------------------------------------------
2352
2353func Test_finally_discard_by_error()
2354  let test =<< trim [CODE]
2355    func E(jump)
2356      let loop = 0
2357      while loop < 2
2358        let loop = loop + 1
2359        if loop == 1
2360          try
2361            if a:jump == "continue"
2362              continue
2363            elseif a:jump == "break"
2364              break
2365            elseif a:jump == "return" || a:jump == "finish"
2366              return
2367            elseif a:jump == "error"
2368              asdf
2369            elseif a:jump == "interrupt"
2370              call interrupt()
2371              let dummy = 0
2372            elseif a:jump == "throw"
2373              throw "abc"
2374            endif
2375          finally
2376            asdf	" error; discards jump that caused the :finally
2377          endtry
2378        elseif loop == 2
2379          call assert_report('should not get here')
2380        endif
2381      endwhile
2382      call assert_report('should not get here')
2383    endfunc
2384
2385    try
2386      Xpath 'a'
2387      call E("continue")
2388      call assert_report('should not get here')
2389    finally
2390      try
2391        Xpath 'b'
2392        call E("break")
2393        call assert_report('should not get here')
2394      finally
2395        try
2396          Xpath 'c'
2397          call E("return")
2398          call assert_report('should not get here')
2399        finally
2400          try
2401            Xpath 'd'
2402            let g:jump = "finish"
2403            ExecAsScript E
2404            call assert_report('should not get here')
2405          finally
2406            unlet g:jump
2407            try
2408              Xpath 'e'
2409              call E("error")
2410              call assert_report('should not get here')
2411            finally
2412              try
2413                Xpath 'f'
2414                call E("interrupt")
2415                call assert_report('should not get here')
2416              finally
2417                try
2418                  Xpath 'g'
2419                  call E("throw")
2420                  call assert_report('should not get here')
2421                finally
2422                  Xpath 'h'
2423                  delfunction E
2424                endtry
2425              endtry
2426            endtry
2427          endtry
2428        endtry
2429      endtry
2430    endtry
2431    call assert_report('should not get here')
2432  [CODE]
2433  let verify =<< trim [CODE]
2434    call assert_equal('abcdefgh', g:Xpath)
2435  [CODE]
2436  call RunInNewVim(test, verify)
2437endfunc
2438
2439"-------------------------------------------------------------------------------
2440" Test 39:  :finally reason discarded by an interrupt			    {{{1
2441"
2442"	    When a :finally clause is executed due to a :continue, :break,
2443"	    :return, :finish, error, interrupt or :throw, the jump reason is
2444"	    discarded by an interrupt in the finally clause.
2445"-------------------------------------------------------------------------------
2446
2447func Test_finally_discarded_by_interrupt()
2448  let test =<< trim [CODE]
2449    func I(jump)
2450      let loop = 0
2451      while loop < 2
2452        let loop = loop + 1
2453        if loop == 1
2454          try
2455            if a:jump == "continue"
2456              continue
2457            elseif a:jump == "break"
2458              break
2459            elseif a:jump == "return" || a:jump == "finish"
2460              return
2461            elseif a:jump == "error"
2462              asdf
2463            elseif a:jump == "interrupt"
2464              call interrupt()
2465              let dummy = 0
2466            elseif a:jump == "throw"
2467              throw "abc"
2468            endif
2469          finally
2470            call interrupt()
2471            let dummy = 0
2472          endtry
2473        elseif loop == 2
2474          call assert_report('should not get here')
2475        endif
2476      endwhile
2477      call assert_report('should not get here')
2478    endfunc
2479
2480    try
2481      try
2482        Xpath 'a'
2483        call I("continue")
2484        call assert_report('should not get here')
2485      finally
2486        try
2487          Xpath 'b'
2488          call I("break")
2489          call assert_report('should not get here')
2490        finally
2491          try
2492            Xpath 'c'
2493            call I("return")
2494            call assert_report('should not get here')
2495          finally
2496            try
2497              Xpath 'd'
2498              let g:jump = "finish"
2499              ExecAsScript I
2500              call assert_report('should not get here')
2501            finally
2502              unlet g:jump
2503              try
2504                Xpath 'e'
2505                call I("error")
2506                call assert_report('should not get here')
2507              finally
2508                try
2509                  Xpath 'f'
2510                  call I("interrupt")
2511                  call assert_report('should not get here')
2512                finally
2513                  try
2514                    Xpath 'g'
2515                    call I("throw")
2516                    call assert_report('should not get here')
2517                  finally
2518                    Xpath 'h'
2519                    delfunction I
2520                  endtry
2521                endtry
2522              endtry
2523            endtry
2524          endtry
2525        endtry
2526      endtry
2527      call assert_report('should not get here')
2528    catch /^Vim:Interrupt$/
2529      Xpath 'A'
2530    endtry
2531  [CODE]
2532  let verify =<< trim [CODE]
2533    call assert_equal('abcdefghA', g:Xpath)
2534  [CODE]
2535  call RunInNewVim(test, verify)
2536endfunc
2537
2538"-------------------------------------------------------------------------------
2539" Test 40:  :finally reason discarded by :throw				    {{{1
2540"
2541"	    When a :finally clause is executed due to a :continue, :break,
2542"	    :return, :finish, error, interrupt or :throw, the jump reason is
2543"	    discarded by a :throw in the finally clause.
2544"-------------------------------------------------------------------------------
2545
2546func Test_finally_discard_by_throw()
2547  let test =<< trim [CODE]
2548    func T(jump)
2549      let loop = 0
2550      while loop < 2
2551        let loop = loop + 1
2552        if loop == 1
2553          try
2554            if a:jump == "continue"
2555              continue
2556            elseif a:jump == "break"
2557              break
2558            elseif a:jump == "return" || a:jump == "finish"
2559              return
2560            elseif a:jump == "error"
2561              asdf
2562            elseif a:jump == "interrupt"
2563              call interrupt()
2564              let dummy = 0
2565            elseif a:jump == "throw"
2566              throw "abc"
2567            endif
2568          finally
2569            throw "xyz"	" discards jump that caused the :finally
2570          endtry
2571        elseif loop == 2
2572          call assert_report('should not get here')
2573        endif
2574      endwhile
2575      call assert_report('should not get here')
2576    endfunc
2577
2578    try
2579      Xpath 'a'
2580      call T("continue")
2581      call assert_report('should not get here')
2582    finally
2583      try
2584        Xpath 'b'
2585        call T("break")
2586        call assert_report('should not get here')
2587      finally
2588        try
2589          Xpath 'c'
2590          call T("return")
2591          call assert_report('should not get here')
2592        finally
2593          try
2594            Xpath 'd'
2595            let g:jump = "finish"
2596            ExecAsScript T
2597            call assert_report('should not get here')
2598          finally
2599            unlet g:jump
2600            try
2601              Xpath 'e'
2602              call T("error")
2603              call assert_report('should not get here')
2604            finally
2605              try
2606                Xpath 'f'
2607                call T("interrupt")
2608                call assert_report('should not get here')
2609              finally
2610                try
2611                  Xpath 'g'
2612                  call T("throw")
2613                  call assert_report('should not get here')
2614                finally
2615                  Xpath 'h'
2616                  delfunction T
2617                endtry
2618              endtry
2619            endtry
2620          endtry
2621        endtry
2622      endtry
2623    endtry
2624    call assert_report('should not get here')
2625  [CODE]
2626  let verify =<< trim [CODE]
2627    call assert_equal('abcdefgh', g:Xpath)
2628  [CODE]
2629  call RunInNewVim(test, verify)
2630endfunc
2631
2632"-------------------------------------------------------------------------------
2633" Test 49:  Throwing exceptions across functions			    {{{1
2634"
2635"	    When an exception is thrown but not caught inside a function, the
2636"	    caller is checked for a matching :catch clause.
2637"-------------------------------------------------------------------------------
2638
2639func T49_C()
2640  try
2641    Xpath 'a'
2642    throw "arrgh"
2643    call assert_report('should not get here')
2644  catch /arrgh/
2645    Xpath 'b'
2646  endtry
2647  Xpath 'c'
2648endfunc
2649
2650func T49_T1()
2651  XloopNEXT
2652  try
2653    Xloop 'd'
2654    throw "arrgh"
2655    call assert_report('should not get here')
2656  finally
2657    Xloop 'e'
2658  endtry
2659  Xloop 'f'
2660endfunc
2661
2662func T49_T2()
2663  try
2664    Xpath 'g'
2665    call T49_T1()
2666    call assert_report('should not get here')
2667  finally
2668    Xpath 'h'
2669  endtry
2670  call assert_report('should not get here')
2671endfunc
2672
2673func Test_throw_exception_across_funcs()
2674  XpathINIT
2675  XloopINIT
2676  try
2677    Xpath 'i'
2678    call T49_C()            " throw and catch
2679    Xpath 'j'
2680  catch /.*/
2681    call assert_report('should not get here')
2682  endtry
2683
2684  try
2685    Xpath 'k'
2686    call T49_T1()  " throw, one level
2687    call assert_report('should not get here')
2688  catch /arrgh/
2689    Xpath 'l'
2690  catch /.*/
2691    call assert_report('should not get here')
2692  endtry
2693
2694  try
2695    Xpath 'm'
2696    call T49_T2()	" throw, two levels
2697    call assert_report('should not get here')
2698  catch /arrgh/
2699    Xpath 'n'
2700  catch /.*/
2701    call assert_report('should not get here')
2702  endtry
2703  Xpath 'o'
2704
2705  call assert_equal('iabcjkd2e2lmgd3e3hno', g:Xpath)
2706endfunc
2707
2708"-------------------------------------------------------------------------------
2709" Test 50:  Throwing exceptions across script files			    {{{1
2710"
2711"	    When an exception is thrown but not caught inside a script file,
2712"	    the sourcing script or function is checked for a matching :catch
2713"	    clause.
2714"
2715"	    This test executes the bodies of the functions C, T1, and T2 from
2716"	    the previous test as script files (:return replaced by :finish).
2717"-------------------------------------------------------------------------------
2718
2719func T50_F()
2720  try
2721    Xpath 'A'
2722    exec "source" g:scriptC
2723    Xpath 'B'
2724  catch /.*/
2725    call assert_report('should not get here')
2726  endtry
2727
2728  try
2729    Xpath 'C'
2730    exec "source" g:scriptT1
2731    call assert_report('should not get here')
2732  catch /arrgh/
2733    Xpath 'D'
2734  catch /.*/
2735    call assert_report('should not get here')
2736  endtry
2737endfunc
2738
2739func Test_throw_across_script()
2740  XpathINIT
2741  XloopINIT
2742  let g:scriptC = MakeScript("T49_C")
2743  let g:scriptT1 = MakeScript("T49_T1")
2744  let scriptT2 = MakeScript("T49_T2", g:scriptT1)
2745
2746  try
2747    Xpath 'E'
2748    call T50_F()
2749    Xpath 'F'
2750    exec "source" scriptT2
2751    call assert_report('should not get here')
2752  catch /arrgh/
2753    Xpath 'G'
2754  catch /.*/
2755    call assert_report('should not get here')
2756  endtry
2757  Xpath 'H'
2758  call assert_equal('EAabcBCd2e2DFgd3e3hGH', g:Xpath)
2759
2760  call delete(g:scriptC)
2761  call delete(g:scriptT1)
2762  call delete(scriptT2)
2763  unlet g:scriptC g:scriptT1 scriptT2
2764endfunc
2765
2766"-------------------------------------------------------------------------------
2767" Test 52:  Uncaught exceptions						    {{{1
2768"
2769"	    When an exception is thrown but not caught, an error message is
2770"	    displayed when the script is terminated.  In case of an interrupt
2771"	    or error exception, the normal interrupt or error message(s) are
2772"	    displayed.
2773"-------------------------------------------------------------------------------
2774
2775func Test_uncaught_exception_1()
2776  CheckEnglish
2777
2778  let test =<< trim [CODE]
2779    Xpath 'a'
2780    throw "arrgh"
2781    call assert_report('should not get here')`
2782  [CODE]
2783  let verify =<< trim [CODE]
2784    call assert_equal('E605: Exception not caught: arrgh', v:errmsg)
2785    call assert_equal('a', g:Xpath)
2786  [CODE]
2787  call RunInNewVim(test, verify)
2788endfunc
2789
2790func Test_uncaught_exception_2()
2791  CheckEnglish
2792
2793  let test =<< trim [CODE]
2794    try
2795      Xpath 'a'
2796      throw "oops"
2797      call assert_report('should not get here')`
2798    catch /arrgh/
2799      call assert_report('should not get here')`
2800    endtry
2801    call assert_report('should not get here')`
2802  [CODE]
2803  let verify =<< trim [CODE]
2804    call assert_equal('E605: Exception not caught: oops', v:errmsg)
2805    call assert_equal('a', g:Xpath)
2806  [CODE]
2807  call RunInNewVim(test, verify)
2808endfunc
2809
2810func Test_uncaught_exception_3()
2811  CheckEnglish
2812
2813  let test =<< trim [CODE]
2814    func T()
2815      Xpath 'c'
2816      throw "brrr"
2817      call assert_report('should not get here')`
2818    endfunc
2819
2820    try
2821      Xpath 'a'
2822      throw "arrgh"
2823      call assert_report('should not get here')`
2824    catch /.*/
2825      Xpath 'b'
2826      call T()
2827      call assert_report('should not get here')`
2828    endtry
2829    call assert_report('should not get here')`
2830  [CODE]
2831  let verify =<< trim [CODE]
2832    call assert_equal('E605: Exception not caught: brrr', v:errmsg)
2833    call assert_equal('abc', g:Xpath)
2834  [CODE]
2835  call RunInNewVim(test, verify)
2836endfunc
2837
2838func Test_uncaught_exception_4()
2839  CheckEnglish
2840
2841  let test =<< trim [CODE]
2842    try
2843      Xpath 'a'
2844      throw "arrgh"
2845      call assert_report('should not get here')`
2846    finally
2847      Xpath 'b'
2848      throw "brrr"
2849      call assert_report('should not get here')`
2850    endtry
2851    call assert_report('should not get here')`
2852  [CODE]
2853  let verify =<< trim [CODE]
2854    call assert_equal('E605: Exception not caught: brrr', v:errmsg)
2855    call assert_equal('ab', g:Xpath)
2856  [CODE]
2857  call RunInNewVim(test, verify)
2858endfunc
2859
2860func Test_uncaught_exception_5()
2861  CheckEnglish
2862
2863  " Need to catch and handle interrupt, otherwise the test will wait for the
2864  " user to press <Enter> to continue
2865  let test =<< trim [CODE]
2866    try
2867      try
2868        Xpath 'a'
2869        call interrupt()
2870        call assert_report('should not get here')
2871      endtry
2872      call assert_report('should not get here')
2873    catch /^Vim:Interrupt$/
2874      Xpath 'b'
2875    endtry
2876  [CODE]
2877  let verify =<< trim [CODE]
2878    call assert_equal('ab', g:Xpath)
2879  [CODE]
2880  call RunInNewVim(test, verify)
2881endfunc
2882
2883func Test_uncaught_exception_6()
2884  CheckEnglish
2885
2886  let test =<< trim [CODE]
2887    try
2888      Xpath 'a'
2889      let x = novar	" error E121; exception: E121
2890    catch /E15:/	" should not catch
2891      call assert_report('should not get here')
2892    endtry
2893    call assert_report('should not get here')
2894  [CODE]
2895  let verify =<< trim [CODE]
2896    call assert_equal('a', g:Xpath)
2897    call assert_equal('E121: Undefined variable: novar', v:errmsg)
2898  [CODE]
2899  call RunInNewVim(test, verify)
2900endfunc
2901
2902func Test_uncaught_exception_7()
2903  CheckEnglish
2904
2905  let test =<< trim [CODE]
2906    try
2907      Xpath 'a'
2908      " error E108/E488; exception: E488
2909      unlet novar #
2910    catch /E108:/       " should not catch
2911      call assert_report('should not get here')
2912    endtry
2913    call assert_report('should not get here')
2914  [CODE]
2915  let verify =<< trim [CODE]
2916    call assert_equal('a', g:Xpath)
2917    call assert_equal('E488: Trailing characters: #', v:errmsg)
2918  [CODE]
2919  call RunInNewVim(test, verify)
2920endfunc
2921
2922"-------------------------------------------------------------------------------
2923" Test 53:  Nesting errors: :endif/:else/:elseif			    {{{1
2924"
2925"	    For nesting errors of :if conditionals the correct error messages
2926"	    should be given.
2927"-------------------------------------------------------------------------------
2928
2929func Test_nested_if_else_errors()
2930  CheckEnglish
2931
2932  " :endif without :if
2933  let code =<< trim END
2934    endif
2935  END
2936  call writefile(code, 'Xtest')
2937  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2938
2939  " :endif without :if
2940  let code =<< trim END
2941    while 1
2942      endif
2943    endwhile
2944  END
2945  call writefile(code, 'Xtest')
2946  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2947
2948  " :endif without :if
2949  let code =<< trim END
2950    try
2951    finally
2952      endif
2953    endtry
2954  END
2955  call writefile(code, 'Xtest')
2956  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2957
2958  " :endif without :if
2959  let code =<< trim END
2960    try
2961      endif
2962    endtry
2963  END
2964  call writefile(code, 'Xtest')
2965  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2966
2967  " :endif without :if
2968  let code =<< trim END
2969    try
2970      throw "a"
2971    catch /a/
2972      endif
2973    endtry
2974  END
2975  call writefile(code, 'Xtest')
2976  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2977
2978  " :else without :if
2979  let code =<< trim END
2980    else
2981  END
2982  call writefile(code, 'Xtest')
2983  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
2984
2985  " :else without :if
2986  let code =<< trim END
2987    while 1
2988      else
2989    endwhile
2990  END
2991  call writefile(code, 'Xtest')
2992  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
2993
2994  " :else without :if
2995  let code =<< trim END
2996    try
2997    finally
2998      else
2999    endtry
3000  END
3001  call writefile(code, 'Xtest')
3002  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
3003
3004  " :else without :if
3005  let code =<< trim END
3006    try
3007      else
3008    endtry
3009  END
3010  call writefile(code, 'Xtest')
3011  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
3012
3013  " :else without :if
3014  let code =<< trim END
3015    try
3016      throw "a"
3017    catch /a/
3018      else
3019    endtry
3020  END
3021  call writefile(code, 'Xtest')
3022  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
3023
3024  " :elseif without :if
3025  let code =<< trim END
3026    elseif
3027  END
3028  call writefile(code, 'Xtest')
3029  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3030
3031  " :elseif without :if
3032  let code =<< trim END
3033    while 1
3034      elseif
3035    endwhile
3036  END
3037  call writefile(code, 'Xtest')
3038  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3039
3040  " :elseif without :if
3041  let code =<< trim END
3042    try
3043    finally
3044      elseif
3045    endtry
3046  END
3047  call writefile(code, 'Xtest')
3048  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3049
3050  " :elseif without :if
3051  let code =<< trim END
3052    try
3053      elseif
3054    endtry
3055  END
3056  call writefile(code, 'Xtest')
3057  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3058
3059  " :elseif without :if
3060  let code =<< trim END
3061    try
3062      throw "a"
3063    catch /a/
3064      elseif
3065    endtry
3066  END
3067  call writefile(code, 'Xtest')
3068  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3069
3070  " multiple :else
3071  let code =<< trim END
3072    if 1
3073    else
3074    else
3075    endif
3076  END
3077  call writefile(code, 'Xtest')
3078  call AssertException(['source Xtest'], 'Vim(else):E583: multiple :else')
3079
3080  " :elseif after :else
3081  let code =<< trim END
3082    if 1
3083    else
3084    elseif 1
3085    endif
3086  END
3087  call writefile(code, 'Xtest')
3088  call AssertException(['source Xtest'], 'Vim(elseif):E584: :elseif after :else')
3089
3090  call delete('Xtest')
3091endfunc
3092
3093"-------------------------------------------------------------------------------
3094" Test 54:  Nesting errors: :while/:endwhile				    {{{1
3095"
3096"	    For nesting errors of :while conditionals the correct error messages
3097"	    should be given.
3098"
3099"	    This test reuses the function MESSAGES() from the previous test.
3100"	    This functions checks the messages in g:msgfile.
3101"-------------------------------------------------------------------------------
3102
3103func Test_nested_while_error()
3104  CheckEnglish
3105
3106  " :endwhile without :while
3107  let code =<< trim END
3108    endwhile
3109  END
3110  call writefile(code, 'Xtest')
3111  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3112
3113  " :endwhile without :while
3114  let code =<< trim END
3115    if 1
3116      endwhile
3117    endif
3118  END
3119  call writefile(code, 'Xtest')
3120  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3121
3122  " Missing :endif
3123  let code =<< trim END
3124    while 1
3125      if 1
3126    endwhile
3127  END
3128  call writefile(code, 'Xtest')
3129  call AssertException(['source Xtest'], 'Vim(endwhile):E171: Missing :endif')
3130
3131  " :endwhile without :while
3132  let code =<< trim END
3133    try
3134    finally
3135      endwhile
3136    endtry
3137  END
3138  call writefile(code, 'Xtest')
3139  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3140
3141  " Missing :endtry
3142  let code =<< trim END
3143    while 1
3144      try
3145      finally
3146    endwhile
3147  END
3148  call writefile(code, 'Xtest')
3149  call AssertException(['source Xtest'], 'Vim(endwhile):E600: Missing :endtry')
3150
3151  " Missing :endtry
3152  let code =<< trim END
3153    while 1
3154      if 1
3155        try
3156        finally
3157    endwhile
3158  END
3159  call writefile(code, 'Xtest')
3160  call AssertException(['source Xtest'], 'Vim(endwhile):E600: Missing :endtry')
3161
3162  " Missing :endif
3163  let code =<< trim END
3164    while 1
3165      try
3166      finally
3167        if 1
3168    endwhile
3169  END
3170  call writefile(code, 'Xtest')
3171  call AssertException(['source Xtest'], 'Vim(endwhile):E171: Missing :endif')
3172
3173  " :endwhile without :while
3174  let code =<< trim END
3175    try
3176      endwhile
3177    endtry
3178  END
3179  call writefile(code, 'Xtest')
3180  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3181
3182  " :endwhile without :while
3183  let code =<< trim END
3184    while 1
3185      try
3186        endwhile
3187      endtry
3188    endwhile
3189  END
3190  call writefile(code, 'Xtest')
3191  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3192
3193  " :endwhile without :while
3194  let code =<< trim END
3195    try
3196      throw "a"
3197    catch /a/
3198      endwhile
3199    endtry
3200  END
3201  call writefile(code, 'Xtest')
3202  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3203
3204  " :endwhile without :while
3205  let code =<< trim END
3206    while 1
3207      try
3208        throw "a"
3209      catch /a/
3210        endwhile
3211      endtry
3212    endwhile
3213  END
3214  call writefile(code, 'Xtest')
3215  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3216
3217  call delete('Xtest')
3218endfunc
3219
3220"-------------------------------------------------------------------------------
3221" Test 55:  Nesting errors: :continue/:break				    {{{1
3222"
3223"	    For nesting errors of :continue and :break commands the correct
3224"	    error messages should be given.
3225"
3226"	    This test reuses the function MESSAGES() from the previous test.
3227"	    This functions checks the messages in g:msgfile.
3228"-------------------------------------------------------------------------------
3229
3230func Test_nested_cont_break_error()
3231  CheckEnglish
3232
3233  " :continue without :while
3234  let code =<< trim END
3235    continue
3236  END
3237  call writefile(code, 'Xtest')
3238  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3239
3240  " :continue without :while
3241  let code =<< trim END
3242    if 1
3243      continue
3244    endif
3245  END
3246  call writefile(code, 'Xtest')
3247  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3248
3249  " :continue without :while
3250  let code =<< trim END
3251    try
3252    finally
3253      continue
3254    endtry
3255  END
3256  call writefile(code, 'Xtest')
3257  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3258
3259  " :continue without :while
3260  let code =<< trim END
3261    try
3262      continue
3263    endtry
3264  END
3265  call writefile(code, 'Xtest')
3266  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3267
3268  " :continue without :while
3269  let code =<< trim END
3270    try
3271      throw "a"
3272    catch /a/
3273      continue
3274    endtry
3275  END
3276  call writefile(code, 'Xtest')
3277  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3278
3279  " :break without :while
3280  let code =<< trim END
3281    break
3282  END
3283  call writefile(code, 'Xtest')
3284  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3285
3286  " :break without :while
3287  let code =<< trim END
3288    if 1
3289      break
3290    endif
3291  END
3292  call writefile(code, 'Xtest')
3293  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3294
3295  " :break without :while
3296  let code =<< trim END
3297    try
3298    finally
3299      break
3300    endtry
3301  END
3302  call writefile(code, 'Xtest')
3303  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3304
3305  " :break without :while
3306  let code =<< trim END
3307    try
3308      break
3309    endtry
3310  END
3311  call writefile(code, 'Xtest')
3312  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3313
3314  " :break without :while
3315  let code =<< trim END
3316    try
3317      throw "a"
3318    catch /a/
3319      break
3320    endtry
3321  END
3322  call writefile(code, 'Xtest')
3323  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3324
3325  call delete('Xtest')
3326endfunc
3327
3328"-------------------------------------------------------------------------------
3329" Test 56:  Nesting errors: :endtry					    {{{1
3330"
3331"	    For nesting errors of :try conditionals the correct error messages
3332"	    should be given.
3333"
3334"	    This test reuses the function MESSAGES() from the previous test.
3335"	    This functions checks the messages in g:msgfile.
3336"-------------------------------------------------------------------------------
3337
3338func Test_nested_endtry_error()
3339  CheckEnglish
3340
3341  " :endtry without :try
3342  let code =<< trim END
3343    endtry
3344  END
3345  call writefile(code, 'Xtest')
3346  call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
3347
3348  " :endtry without :try
3349  let code =<< trim END
3350    if 1
3351      endtry
3352    endif
3353  END
3354  call writefile(code, 'Xtest')
3355  call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
3356
3357  " :endtry without :try
3358  let code =<< trim END
3359    while 1
3360      endtry
3361    endwhile
3362  END
3363  call writefile(code, 'Xtest')
3364  call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
3365
3366  " Missing :endif
3367  let code =<< trim END
3368    try
3369        if 1
3370    endtry
3371  END
3372  call writefile(code, 'Xtest')
3373  call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
3374
3375  " Missing :endwhile
3376  let code =<< trim END
3377    try
3378      while 1
3379    endtry
3380  END
3381  call writefile(code, 'Xtest')
3382  call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
3383
3384  " Missing :endif
3385  let code =<< trim END
3386    try
3387    finally
3388      if 1
3389    endtry
3390  END
3391  call writefile(code, 'Xtest')
3392  call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
3393
3394  " Missing :endwhile
3395  let code =<< trim END
3396    try
3397    finally
3398      while 1
3399    endtry
3400  END
3401  call writefile(code, 'Xtest')
3402  call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
3403
3404  " Missing :endif
3405  let code =<< trim END
3406    try
3407      throw "a"
3408    catch /a/
3409      if 1
3410    endtry
3411  END
3412  call writefile(code, 'Xtest')
3413  call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
3414
3415  " Missing :endwhile
3416  let code =<< trim END
3417    try
3418      throw "a"
3419    catch /a/
3420      while 1
3421    endtry
3422  END
3423  call writefile(code, 'Xtest')
3424  call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
3425
3426  call delete('Xtest')
3427endfunc
3428
3429"-------------------------------------------------------------------------------
3430" Test 57:  v:exception and v:throwpoint for user exceptions		    {{{1
3431"
3432"	    v:exception evaluates to the value of the exception that was caught
3433"	    most recently and is not finished.  (A caught exception is finished
3434"	    when the next ":catch", ":finally", or ":endtry" is reached.)
3435"	    v:throwpoint evaluates to the script/function name and line number
3436"	    where that exception has been thrown.
3437"-------------------------------------------------------------------------------
3438
3439func Test_user_exception_info()
3440  CheckEnglish
3441
3442  XpathINIT
3443  XloopINIT
3444
3445  func FuncException()
3446    let g:exception = v:exception
3447  endfunc
3448
3449  func FuncThrowpoint()
3450    let g:throwpoint = v:throwpoint
3451  endfunc
3452
3453  let scriptException  = MakeScript("FuncException")
3454  let scriptThrowPoint = MakeScript("FuncThrowpoint")
3455
3456  command! CmdException  let g:exception  = v:exception
3457  command! CmdThrowpoint let g:throwpoint = v:throwpoint
3458
3459  func T(arg, line)
3460    if a:line == 2
3461      throw a:arg		" in line 2
3462    elseif a:line == 4
3463      throw a:arg		" in line 4
3464    elseif a:line == 6
3465      throw a:arg		" in line 6
3466    elseif a:line == 8
3467      throw a:arg		" in line 8
3468    endif
3469  endfunc
3470
3471  func G(arg, line)
3472    call T(a:arg, a:line)
3473  endfunc
3474
3475  func F(arg, line)
3476    call G(a:arg, a:line)
3477  endfunc
3478
3479  let scriptT = MakeScript("T")
3480  let scriptG = MakeScript("G", scriptT)
3481  let scriptF = MakeScript("F", scriptG)
3482
3483  try
3484    Xpath 'a'
3485    call F("oops", 2)
3486  catch /.*/
3487    Xpath 'b'
3488    let exception  = v:exception
3489    let throwpoint = v:throwpoint
3490    call assert_equal("oops", v:exception)
3491    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3492    call assert_match('\<2\>', v:throwpoint)
3493
3494    exec "let exception  = v:exception"
3495    exec "let throwpoint = v:throwpoint"
3496    call assert_equal("oops", v:exception)
3497    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3498    call assert_match('\<2\>', v:throwpoint)
3499
3500    CmdException
3501    CmdThrowpoint
3502    call assert_equal("oops", v:exception)
3503    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3504    call assert_match('\<2\>', v:throwpoint)
3505
3506    call FuncException()
3507    call FuncThrowpoint()
3508    call assert_equal("oops", v:exception)
3509    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3510    call assert_match('\<2\>', v:throwpoint)
3511
3512    exec "source" scriptException
3513    exec "source" scriptThrowPoint
3514    call assert_equal("oops", v:exception)
3515    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3516    call assert_match('\<2\>', v:throwpoint)
3517
3518    try
3519      Xpath 'c'
3520      call G("arrgh", 4)
3521    catch /.*/
3522      Xpath 'd'
3523      let exception  = v:exception
3524      let throwpoint = v:throwpoint
3525      call assert_equal("arrgh", v:exception)
3526      call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3527      call assert_match('\<4\>', v:throwpoint)
3528
3529      try
3530        Xpath 'e'
3531        let g:arg = "autsch"
3532        let g:line = 6
3533        exec "source" scriptF
3534      catch /.*/
3535        Xpath 'f'
3536        let exception  = v:exception
3537        let throwpoint = v:throwpoint
3538        call assert_equal("autsch", v:exception)
3539        call assert_match(fnamemodify(scriptT, ':t'), v:throwpoint)
3540        call assert_match('\<6\>', v:throwpoint)
3541      finally
3542        Xpath 'g'
3543        let exception  = v:exception
3544        let throwpoint = v:throwpoint
3545        call assert_equal("arrgh", v:exception)
3546        call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3547        call assert_match('\<4\>', v:throwpoint)
3548        try
3549          Xpath 'h'
3550          let g:arg = "brrrr"
3551          let g:line = 8
3552          exec "source" scriptG
3553        catch /.*/
3554          Xpath 'i'
3555          let exception  = v:exception
3556          let throwpoint = v:throwpoint
3557          " Resolve scriptT for matching it against v:throwpoint.
3558          call assert_equal("brrrr", v:exception)
3559          call assert_match(fnamemodify(scriptT, ':t'), v:throwpoint)
3560          call assert_match('\<8\>', v:throwpoint)
3561        finally
3562          Xpath 'j'
3563          let exception  = v:exception
3564          let throwpoint = v:throwpoint
3565          call assert_equal("arrgh", v:exception)
3566          call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3567          call assert_match('\<4\>', v:throwpoint)
3568        endtry
3569        Xpath 'k'
3570        let exception  = v:exception
3571        let throwpoint = v:throwpoint
3572        call assert_equal("arrgh", v:exception)
3573        call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3574        call assert_match('\<4\>', v:throwpoint)
3575      endtry
3576      Xpath 'l'
3577      let exception  = v:exception
3578      let throwpoint = v:throwpoint
3579      call assert_equal("arrgh", v:exception)
3580      call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3581      call assert_match('\<4\>', v:throwpoint)
3582    finally
3583      Xpath 'm'
3584      let exception  = v:exception
3585      let throwpoint = v:throwpoint
3586      call assert_equal("oops", v:exception)
3587      call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3588      call assert_match('\<2\>', v:throwpoint)
3589    endtry
3590    Xpath 'n'
3591    let exception  = v:exception
3592    let throwpoint = v:throwpoint
3593    call assert_equal("oops", v:exception)
3594    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3595    call assert_match('\<2\>', v:throwpoint)
3596  finally
3597    Xpath 'o'
3598    let exception  = v:exception
3599    let throwpoint = v:throwpoint
3600    call assert_equal("", v:exception)
3601    call assert_match('^$', v:throwpoint)
3602    call assert_match('^$', v:throwpoint)
3603  endtry
3604
3605  call assert_equal('abcdefghijklmno', g:Xpath)
3606
3607  unlet exception throwpoint
3608  delfunction FuncException
3609  delfunction FuncThrowpoint
3610  call delete(scriptException)
3611  call delete(scriptThrowPoint)
3612  unlet scriptException scriptThrowPoint
3613  delcommand CmdException
3614  delcommand CmdThrowpoint
3615  delfunction T
3616  delfunction G
3617  delfunction F
3618  call delete(scriptT)
3619  call delete(scriptG)
3620  call delete(scriptF)
3621  unlet scriptT scriptG scriptF
3622endfunc
3623
3624"-------------------------------------------------------------------------------
3625"
3626" Test 58:  v:exception and v:throwpoint for error/interrupt exceptions	    {{{1
3627"
3628"	    v:exception and v:throwpoint work also for error and interrupt
3629"	    exceptions.
3630"-------------------------------------------------------------------------------
3631
3632func Test_execption_info_for_error()
3633  CheckEnglish
3634
3635  let test =<< trim [CODE]
3636    func T(line)
3637      if a:line == 2
3638        delfunction T		" error (function in use) in line 2
3639      elseif a:line == 4
3640        call interrupt()
3641      endif
3642    endfunc
3643
3644    while 1
3645      try
3646        Xpath 'a'
3647        call T(2)
3648        call assert_report('should not get here')
3649      catch /.*/
3650        Xpath 'b'
3651        if v:exception !~ 'Vim(delfunction):'
3652          call assert_report('should not get here')
3653        endif
3654        if v:throwpoint !~ '\<T\>'
3655          call assert_report('should not get here')
3656        endif
3657        if v:throwpoint !~ '\<2\>'
3658          call assert_report('should not get here')
3659        endif
3660      finally
3661        Xpath 'c'
3662        if v:exception != ""
3663          call assert_report('should not get here')
3664        endif
3665        if v:throwpoint != ""
3666          call assert_report('should not get here')
3667        endif
3668        break
3669      endtry
3670    endwhile
3671
3672    Xpath 'd'
3673    if v:exception != ""
3674      call assert_report('should not get here')
3675    endif
3676    if v:throwpoint != ""
3677      call assert_report('should not get here')
3678    endif
3679
3680    while 1
3681      try
3682        Xpath 'e'
3683        call T(4)
3684        call assert_report('should not get here')
3685      catch /.*/
3686        Xpath 'f'
3687        if v:exception != 'Vim:Interrupt'
3688          call assert_report('should not get here')
3689        endif
3690        if v:throwpoint !~ 'function T'
3691          call assert_report('should not get here')
3692        endif
3693        if v:throwpoint !~ '\<4\>'
3694          call assert_report('should not get here')
3695        endif
3696      finally
3697        Xpath 'g'
3698        if v:exception != ""
3699          call assert_report('should not get here')
3700        endif
3701        if v:throwpoint != ""
3702          call assert_report('should not get here')
3703        endif
3704        break
3705      endtry
3706    endwhile
3707
3708    Xpath 'h'
3709    if v:exception != ""
3710      call assert_report('should not get here')
3711    endif
3712    if v:throwpoint != ""
3713      call assert_report('should not get here')
3714    endif
3715  [CODE]
3716  let verify =<< trim [CODE]
3717    call assert_equal('abcdefgh', g:Xpath)
3718  [CODE]
3719  call RunInNewVim(test, verify)
3720endfunc
3721
3722"-------------------------------------------------------------------------------
3723" Test 61:  Catching interrupt exceptions				    {{{1
3724"
3725"	    When an interrupt occurs inside a :try/:endtry region, an
3726"	    interrupt exception is thrown and can be caught.  Its value is
3727"	    "Vim:Interrupt".  If the interrupt occurs after an error or a :throw
3728"	    but before a matching :catch is reached, all following :catches of
3729"	    that try block are ignored, but the interrupt exception can be
3730"	    caught by the next surrounding try conditional.  An interrupt is
3731"	    ignored when there is a previous interrupt that has not been caught
3732"	    or causes a :finally clause to be executed.
3733"-------------------------------------------------------------------------------
3734
3735func Test_catch_intr_exception()
3736  let test =<< trim [CODE]
3737    while 1
3738      try
3739        try
3740          Xpath 'a'
3741          call interrupt()
3742          call assert_report('should not get here')
3743        catch /^Vim:Interrupt$/
3744          Xpath 'b'
3745        finally
3746          Xpath 'c'
3747        endtry
3748      catch /.*/
3749        call assert_report('should not get here')
3750      finally
3751        Xpath 'd'
3752        break
3753      endtry
3754    endwhile
3755
3756    while 1
3757      try
3758        try
3759          try
3760            Xpath 'e'
3761            asdf
3762            call assert_report('should not get here')
3763          catch /do_not_catch/
3764            call assert_report('should not get here')
3765          catch /.*/
3766            Xpath 'f'
3767            call interrupt()
3768            call assert_report('should not get here')
3769          catch /.*/
3770            call assert_report('should not get here')
3771          finally
3772            Xpath 'g'
3773            call interrupt()
3774            call assert_report('should not get here')
3775          endtry
3776        catch /^Vim:Interrupt$/
3777          Xpath 'h'
3778        finally
3779          Xpath 'i'
3780        endtry
3781      catch /.*/
3782        call assert_report('should not get here')
3783      finally
3784        Xpath 'j'
3785        break
3786      endtry
3787    endwhile
3788
3789    while 1
3790      try
3791        try
3792          try
3793            Xpath 'k'
3794            throw "x"
3795            call assert_report('should not get here')
3796          catch /do_not_catch/
3797            call assert_report('should not get here')
3798          catch /x/
3799            Xpath 'l'
3800            call interrupt()
3801            call assert_report('should not get here')
3802          catch /.*/
3803            call assert_report('should not get here')
3804          endtry
3805        catch /^Vim:Interrupt$/
3806          Xpath 'm'
3807        finally
3808          Xpath 'n'
3809        endtry
3810      catch /.*/
3811        call assert_report('should not get here')
3812      finally
3813        Xpath 'o'
3814        break
3815      endtry
3816    endwhile
3817
3818    while 1
3819      try
3820        try
3821          Xpath 'p'
3822          call interrupt()
3823          call assert_report('should not get here')
3824        catch /do_not_catch/
3825          call interrupt()
3826          call assert_report('should not get here')
3827        catch /^Vim:Interrupt$/
3828          Xpath 'q'
3829        finally
3830          Xpath 'r'
3831        endtry
3832      catch /.*/
3833        call assert_report('should not get here')
3834      finally
3835        Xpath 's'
3836        break
3837      endtry
3838    endwhile
3839
3840    Xpath 't'
3841  [CODE]
3842  let verify =<< trim [CODE]
3843    call assert_equal('abcdefghijklmnopqrst', g:Xpath)
3844  [CODE]
3845  call RunInNewVim(test, verify)
3846endfunc
3847
3848"-------------------------------------------------------------------------------
3849" Test 65:  Errors in the /pattern/ argument of a :catch		    {{{1
3850"
3851"	    On an error in the /pattern/ argument of a :catch, the :catch does
3852"	    not match.  Any following :catches of the same :try/:endtry don't
3853"	    match either.  Finally clauses are executed.
3854"-------------------------------------------------------------------------------
3855
3856func Test_catch_pattern_error()
3857  CheckEnglish
3858  XpathINIT
3859
3860  try
3861    try
3862      Xpath 'a'
3863      throw "oops"
3864    catch /^oops$/
3865      Xpath 'b'
3866    catch /\)/		" not checked; exception has already been caught
3867      call assert_report('should not get here')
3868    endtry
3869    Xpath 'c'
3870  catch /.*/
3871    call assert_report('should not get here')
3872  endtry
3873  call assert_equal('abc', g:Xpath)
3874
3875  XpathINIT
3876  func F()
3877    try
3878      try
3879        try
3880          Xpath 'a'
3881          throw "ab"
3882        catch /abc/	" does not catch
3883          call assert_report('should not get here')
3884        catch /\)/	" error; discards exception
3885          call assert_report('should not get here')
3886        catch /.*/	" not checked
3887          call assert_report('should not get here')
3888        finally
3889          Xpath 'b'
3890        endtry
3891        call assert_report('should not get here')
3892      catch /^ab$/	" checked, but original exception is discarded
3893        call assert_report('should not get here')
3894      catch /^Vim(catch):/
3895        Xpath 'c'
3896        call assert_match('Vim(catch):E475: Invalid argument:', v:exception)
3897      finally
3898        Xpath 'd'
3899      endtry
3900      Xpath 'e'
3901    catch /.*/
3902      call assert_report('should not get here')
3903    endtry
3904    Xpath 'f'
3905  endfunc
3906
3907  call F()
3908  call assert_equal('abcdef', g:Xpath)
3909
3910  delfunc F
3911endfunc
3912
3913"-------------------------------------------------------------------------------
3914" Test 87   using (expr) ? funcref : funcref				    {{{1
3915"
3916"	    Vim needs to correctly parse the funcref and even when it does
3917"	    not execute the funcref, it needs to consume the trailing ()
3918"-------------------------------------------------------------------------------
3919
3920func Add2(x1, x2)
3921  return a:x1 + a:x2
3922endfu
3923
3924func GetStr()
3925  return "abcdefghijklmnopqrstuvwxyp"
3926endfu
3927
3928func Test_funcref_with_condexpr()
3929  call assert_equal(5, function('Add2')(2,3))
3930
3931  call assert_equal(3, 1 ? function('Add2')(1,2) : function('Add2')(2,3))
3932  call assert_equal(5, 0 ? function('Add2')(1,2) : function('Add2')(2,3))
3933  " Make sure, GetStr() still works.
3934  call assert_equal('abcdefghijk', GetStr()[0:10])
3935endfunc
3936
3937" Test 90:  Recognizing {} in variable name.			    {{{1
3938"-------------------------------------------------------------------------------
3939
3940func Test_curlies()
3941    let s:var = 66
3942    let ns = 's'
3943    call assert_equal(66, {ns}:var)
3944
3945    let g:a = {}
3946    let g:b = 't'
3947    let g:a[g:b] = 77
3948    call assert_equal(77, g:a['t'])
3949endfunc
3950
3951"-------------------------------------------------------------------------------
3952" Test 91:  using type().					    {{{1
3953"-------------------------------------------------------------------------------
3954
3955func Test_type()
3956    call assert_equal(0, type(0))
3957    call assert_equal(1, type(""))
3958    call assert_equal(2, type(function("tr")))
3959    call assert_equal(2, type(function("tr", [8])))
3960    call assert_equal(3, type([]))
3961    call assert_equal(4, type({}))
3962    if has('float')
3963      call assert_equal(5, type(0.0))
3964    endif
3965    call assert_equal(6, type(v:false))
3966    call assert_equal(6, type(v:true))
3967    call assert_equal(7, type(v:none))
3968    call assert_equal(7, type(v:null))
3969    call assert_equal(8, v:t_job)
3970    call assert_equal(9, v:t_channel)
3971    call assert_equal(v:t_number, type(0))
3972    call assert_equal(v:t_string, type(""))
3973    call assert_equal(v:t_func, type(function("tr")))
3974    call assert_equal(v:t_func, type(function("tr", [8])))
3975    call assert_equal(v:t_list, type([]))
3976    call assert_equal(v:t_dict, type({}))
3977    if has('float')
3978      call assert_equal(v:t_float, type(0.0))
3979    endif
3980    call assert_equal(v:t_bool, type(v:false))
3981    call assert_equal(v:t_bool, type(v:true))
3982    call assert_equal(v:t_none, type(v:none))
3983    call assert_equal(v:t_none, type(v:null))
3984    call assert_equal(v:t_string, type(test_null_string()))
3985    call assert_equal(v:t_func, type(test_null_function()))
3986    call assert_equal(v:t_func, type(test_null_partial()))
3987    call assert_equal(v:t_list, type(test_null_list()))
3988    call assert_equal(v:t_dict, type(test_null_dict()))
3989    if has('job')
3990      call assert_equal(v:t_job, type(test_null_job()))
3991    endif
3992    if has('channel')
3993      call assert_equal(v:t_channel, type(test_null_channel()))
3994    endif
3995    call assert_equal(v:t_blob, type(test_null_blob()))
3996
3997    call assert_fails("call type(test_void())", 'E685:')
3998    call assert_fails("call type(test_unknown())", 'E685:')
3999
4000    call assert_equal(0, 0 + v:false)
4001    call assert_equal(1, 0 + v:true)
4002    call assert_equal(0, 0 + v:none)
4003    call assert_equal(0, 0 + v:null)
4004
4005    call assert_equal('v:false', '' . v:false)
4006    call assert_equal('v:true', '' . v:true)
4007    call assert_equal('v:none', '' . v:none)
4008    call assert_equal('v:null', '' . v:null)
4009
4010    call assert_true(v:false == 0)
4011    call assert_false(v:false != 0)
4012    call assert_true(v:true == 1)
4013    call assert_false(v:true != 1)
4014    call assert_false(v:true == v:false)
4015    call assert_true(v:true != v:false)
4016
4017    call assert_true(v:null == 0)
4018    call assert_false(v:null != 0)
4019    call assert_true(v:none == 0)
4020    call assert_false(v:none != 0)
4021
4022    call assert_true(v:false is v:false)
4023    call assert_true(v:true is v:true)
4024    call assert_true(v:none is v:none)
4025    call assert_true(v:null is v:null)
4026
4027    call assert_false(v:false isnot v:false)
4028    call assert_false(v:true isnot v:true)
4029    call assert_false(v:none isnot v:none)
4030    call assert_false(v:null isnot v:null)
4031
4032    call assert_false(v:false is 0)
4033    call assert_false(v:true is 1)
4034    call assert_false(v:true is v:false)
4035    call assert_false(v:none is 0)
4036    call assert_false(v:null is 0)
4037    call assert_false(v:null is v:none)
4038
4039    call assert_true(v:false isnot 0)
4040    call assert_true(v:true isnot 1)
4041    call assert_true(v:true isnot v:false)
4042    call assert_true(v:none isnot 0)
4043    call assert_true(v:null isnot 0)
4044    call assert_true(v:null isnot v:none)
4045
4046    call assert_equal(v:false, eval(string(v:false)))
4047    call assert_equal(v:true, eval(string(v:true)))
4048    call assert_equal(v:none, eval(string(v:none)))
4049    call assert_equal(v:null, eval(string(v:null)))
4050
4051    call assert_equal(v:false, copy(v:false))
4052    call assert_equal(v:true, copy(v:true))
4053    call assert_equal(v:none, copy(v:none))
4054    call assert_equal(v:null, copy(v:null))
4055
4056    call assert_equal([v:false], deepcopy([v:false]))
4057    call assert_equal([v:true], deepcopy([v:true]))
4058    call assert_equal([v:none], deepcopy([v:none]))
4059    call assert_equal([v:null], deepcopy([v:null]))
4060
4061    call assert_true(empty(v:false))
4062    call assert_false(empty(v:true))
4063    call assert_true(empty(v:null))
4064    call assert_true(empty(v:none))
4065
4066    func ChangeYourMind()
4067	try
4068	    return v:true
4069	finally
4070	    return 'something else'
4071	endtry
4072    endfunc
4073
4074    call ChangeYourMind()
4075endfunc
4076
4077"-------------------------------------------------------------------------------
4078" Test 92:  skipping code					    {{{1
4079"-------------------------------------------------------------------------------
4080
4081func Test_skip()
4082    let Fn = function('Test_type')
4083    call assert_false(0 && Fn[1])
4084    call assert_false(0 && string(Fn))
4085    call assert_false(0 && len(Fn))
4086    let l = []
4087    call assert_false(0 && l[1])
4088    call assert_false(0 && string(l))
4089    call assert_false(0 && len(l))
4090    let f = 1.0
4091    call assert_false(0 && f[1])
4092    call assert_false(0 && string(f))
4093    call assert_false(0 && len(f))
4094    let sp = v:null
4095    call assert_false(0 && sp[1])
4096    call assert_false(0 && string(sp))
4097    call assert_false(0 && len(sp))
4098
4099endfunc
4100
4101"-------------------------------------------------------------------------------
4102" Test 93:  :echo and string()					    {{{1
4103"-------------------------------------------------------------------------------
4104
4105func Test_echo_and_string()
4106    " String
4107    let a = 'foo bar'
4108    redir => result
4109    echo a
4110    echo string(a)
4111    redir END
4112    let l = split(result, "\n")
4113    call assert_equal(["foo bar",
4114		     \ "'foo bar'"], l)
4115
4116    " Float
4117    if has('float')
4118	let a = -1.2e0
4119	redir => result
4120	echo a
4121	echo string(a)
4122	redir END
4123	let l = split(result, "\n")
4124	call assert_equal(["-1.2",
4125			 \ "-1.2"], l)
4126    endif
4127
4128    " Funcref
4129    redir => result
4130    echo function('string')
4131    echo string(function('string'))
4132    redir END
4133    let l = split(result, "\n")
4134    call assert_equal(["string",
4135		     \ "function('string')"], l)
4136
4137    " Recursive dictionary
4138    let a = {}
4139    let a["a"] = a
4140    redir => result
4141    echo a
4142    echo string(a)
4143    redir END
4144    let l = split(result, "\n")
4145    call assert_equal(["{'a': {...}}",
4146		     \ "{'a': {...}}"], l)
4147
4148    " Recursive list
4149    let a = [0]
4150    let a[0] = a
4151    redir => result
4152    echo a
4153    echo string(a)
4154    redir END
4155    let l = split(result, "\n")
4156    call assert_equal(["[[...]]",
4157		     \ "[[...]]"], l)
4158
4159    " Empty dictionaries in a list
4160    let a = {}
4161    redir => result
4162    echo [a, a, a]
4163    echo string([a, a, a])
4164    redir END
4165    let l = split(result, "\n")
4166    call assert_equal(["[{}, {}, {}]",
4167		     \ "[{}, {}, {}]"], l)
4168
4169    " Empty dictionaries in a dictionary
4170    let a = {}
4171    let b = {"a": a, "b": a}
4172    redir => result
4173    echo b
4174    echo string(b)
4175    redir END
4176    let l = split(result, "\n")
4177    call assert_equal(["{'a': {}, 'b': {}}",
4178		     \ "{'a': {}, 'b': {}}"], l)
4179
4180    " Empty lists in a list
4181    let a = []
4182    redir => result
4183    echo [a, a, a]
4184    echo string([a, a, a])
4185    redir END
4186    let l = split(result, "\n")
4187    call assert_equal(["[[], [], []]",
4188		     \ "[[], [], []]"], l)
4189
4190    " Empty lists in a dictionary
4191    let a = []
4192    let b = {"a": a, "b": a}
4193    redir => result
4194    echo b
4195    echo string(b)
4196    redir END
4197    let l = split(result, "\n")
4198    call assert_equal(["{'a': [], 'b': []}",
4199		     \ "{'a': [], 'b': []}"], l)
4200
4201    " Dictionaries in a list
4202    let a = {"one": "yes", "two": "yes", "three": "yes"}
4203    redir => result
4204    echo [a, a, a]
4205    echo string([a, a, a])
4206    redir END
4207    let l = split(result, "\n")
4208    call assert_equal(["[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {...}, {...}]",
4209		     \ "[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}]"], l)
4210
4211    " Dictionaries in a dictionary
4212    let a = {"one": "yes", "two": "yes", "three": "yes"}
4213    let b = {"a": a, "b": a}
4214    redir => result
4215    echo b
4216    echo string(b)
4217    redir END
4218    let l = split(result, "\n")
4219    call assert_equal(["{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {...}}",
4220		     \ "{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {'one': 'yes', 'two': 'yes', 'three': 'yes'}}"], l)
4221
4222    " Lists in a list
4223    let a = [1, 2, 3]
4224    redir => result
4225    echo [a, a, a]
4226    echo string([a, a, a])
4227    redir END
4228    let l = split(result, "\n")
4229    call assert_equal(["[[1, 2, 3], [...], [...]]",
4230		     \ "[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"], l)
4231
4232    " Lists in a dictionary
4233    let a = [1, 2, 3]
4234    let b = {"a": a, "b": a}
4235    redir => result
4236    echo b
4237    echo string(b)
4238    redir END
4239    let l = split(result, "\n")
4240    call assert_equal(["{'a': [1, 2, 3], 'b': [...]}",
4241		     \ "{'a': [1, 2, 3], 'b': [1, 2, 3]}"], l)
4242
4243    call assert_fails('echo &:', 'E112:')
4244    call assert_fails('echo &g:', 'E112:')
4245    call assert_fails('echo &l:', 'E112:')
4246
4247endfunc
4248
4249"-------------------------------------------------------------------------------
4250" Test 94:  64-bit Numbers					    {{{1
4251"-------------------------------------------------------------------------------
4252
4253func Test_num64()
4254    call assert_notequal( 4294967296, 0)
4255    call assert_notequal(-4294967296, 0)
4256    call assert_equal( 4294967296,  0xFFFFffff + 1)
4257    call assert_equal(-4294967296, -0xFFFFffff - 1)
4258
4259    call assert_equal( 9223372036854775807,  1 / 0)
4260    call assert_equal(-9223372036854775807, -1 / 0)
4261    call assert_equal(-9223372036854775807 - 1,  0 / 0)
4262
4263    if has('float')
4264      call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150))
4265      call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150))
4266    endif
4267
4268    let rng = range(0xFFFFffff, 0x100000001)
4269    call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng)
4270    call assert_equal(0x100000001, max(rng))
4271    call assert_equal(0xFFFFffff, min(rng))
4272    call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N'))
4273endfunc
4274
4275"-------------------------------------------------------------------------------
4276" Test 95:  lines of :append, :change, :insert			    {{{1
4277"-------------------------------------------------------------------------------
4278
4279function! DefineFunction(name, body)
4280    let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n")
4281    exec func
4282endfunction
4283
4284func Test_script_lines()
4285    " :append
4286    try
4287	call DefineFunction('T_Append', [
4288		    \ 'append',
4289		    \ 'py <<EOS',
4290		    \ '.',
4291		    \ ])
4292    catch
4293	call assert_report("Can't define function")
4294    endtry
4295    try
4296	call DefineFunction('T_Append', [
4297		    \ 'append',
4298		    \ 'abc',
4299		    \ ])
4300	call assert_report("Shouldn't be able to define function")
4301    catch
4302	call assert_exception('Vim(function):E126: Missing :endfunction')
4303    endtry
4304
4305    " :change
4306    try
4307	call DefineFunction('T_Change', [
4308		    \ 'change',
4309		    \ 'py <<EOS',
4310		    \ '.',
4311		    \ ])
4312    catch
4313	call assert_report("Can't define function")
4314    endtry
4315    try
4316	call DefineFunction('T_Change', [
4317		    \ 'change',
4318		    \ 'abc',
4319		    \ ])
4320	call assert_report("Shouldn't be able to define function")
4321    catch
4322	call assert_exception('Vim(function):E126: Missing :endfunction')
4323    endtry
4324
4325    " :insert
4326    try
4327	call DefineFunction('T_Insert', [
4328		    \ 'insert',
4329		    \ 'py <<EOS',
4330		    \ '.',
4331		    \ ])
4332    catch
4333	call assert_report("Can't define function")
4334    endtry
4335    try
4336	call DefineFunction('T_Insert', [
4337		    \ 'insert',
4338		    \ 'abc',
4339		    \ ])
4340	call assert_report("Shouldn't be able to define function")
4341    catch
4342	call assert_exception('Vim(function):E126: Missing :endfunction')
4343    endtry
4344endfunc
4345
4346"-------------------------------------------------------------------------------
4347" Test 96:  line continuation						    {{{1
4348"
4349"	    Undefined behavior was detected by ubsan with line continuation
4350"	    after an empty line.
4351"-------------------------------------------------------------------------------
4352func Test_script_emty_line_continuation()
4353
4354    \
4355endfunc
4356
4357"-------------------------------------------------------------------------------
4358" Test 97:  bitwise functions						    {{{1
4359"-------------------------------------------------------------------------------
4360func Test_bitwise_functions()
4361    " and
4362    call assert_equal(127, and(127, 127))
4363    call assert_equal(16, and(127, 16))
4364    eval 127->and(16)->assert_equal(16)
4365    call assert_equal(0, and(127, 128))
4366    call assert_fails("call and([], 1)", 'E745:')
4367    call assert_fails("call and({}, 1)", 'E728:')
4368    if has('float')
4369      call assert_fails("call and(1.0, 1)", 'E805:')
4370      call assert_fails("call and(1, 1.0)", 'E805:')
4371    endif
4372    call assert_fails("call and(1, [])", 'E745:')
4373    call assert_fails("call and(1, {})", 'E728:')
4374    " or
4375    call assert_equal(23, or(16, 7))
4376    call assert_equal(15, or(8, 7))
4377    eval 8->or(7)->assert_equal(15)
4378    call assert_equal(123, or(0, 123))
4379    call assert_fails("call or([], 1)", 'E745:')
4380    call assert_fails("call or({}, 1)", 'E728:')
4381    if has('float')
4382      call assert_fails("call or(1.0, 1)", 'E805:')
4383      call assert_fails("call or(1, 1.0)", 'E805:')
4384    endif
4385    call assert_fails("call or(1, [])", 'E745:')
4386    call assert_fails("call or(1, {})", 'E728:')
4387    " xor
4388    call assert_equal(0, xor(127, 127))
4389    call assert_equal(111, xor(127, 16))
4390    eval 127->xor(16)->assert_equal(111)
4391    call assert_equal(255, xor(127, 128))
4392    if has('float')
4393      call assert_fails("call xor(1.0, 1)", 'E805:')
4394      call assert_fails("call xor(1, 1.0)", 'E805:')
4395    endif
4396    call assert_fails("call xor([], 1)", 'E745:')
4397    call assert_fails("call xor({}, 1)", 'E728:')
4398    call assert_fails("call xor(1, [])", 'E745:')
4399    call assert_fails("call xor(1, {})", 'E728:')
4400    " invert
4401    call assert_equal(65408, and(invert(127), 65535))
4402    eval 127->invert()->and(65535)->assert_equal(65408)
4403    call assert_equal(65519, and(invert(16), 65535))
4404    call assert_equal(65407, and(invert(128), 65535))
4405    if has('float')
4406      call assert_fails("call invert(1.0)", 'E805:')
4407    endif
4408    call assert_fails("call invert([])", 'E745:')
4409    call assert_fails("call invert({})", 'E728:')
4410endfunc
4411
4412" Test using bang after user command				    {{{1
4413func Test_user_command_with_bang()
4414    command -bang Nieuw let nieuw = 1
4415    Ni!
4416    call assert_equal(1, nieuw)
4417    unlet nieuw
4418    delcommand Nieuw
4419endfunc
4420
4421func Test_script_expand_sfile()
4422  let lines =<< trim END
4423    func s:snr()
4424      return expand('<sfile>')
4425    endfunc
4426    let g:result = s:snr()
4427  END
4428  call writefile(lines, 'Xexpand')
4429  source Xexpand
4430  call assert_match('<SNR>\d\+_snr', g:result)
4431  source Xexpand
4432  call assert_match('<SNR>\d\+_snr', g:result)
4433
4434  call delete('Xexpand')
4435  unlet g:result
4436endfunc
4437
4438func Test_compound_assignment_operators()
4439    " Test for number
4440    let x = 1
4441    let x += 10
4442    call assert_equal(11, x)
4443    let x -= 5
4444    call assert_equal(6, x)
4445    let x *= 4
4446    call assert_equal(24, x)
4447    let x /= 3
4448    call assert_equal(8, x)
4449    let x %= 3
4450    call assert_equal(2, x)
4451    let x .= 'n'
4452    call assert_equal('2n', x)
4453
4454    " Test special cases: division or modulus with 0.
4455    let x = 1
4456    let x /= 0
4457    call assert_equal(0x7FFFFFFFFFFFFFFF, x)
4458
4459    let x = -1
4460    let x /= 0
4461    call assert_equal(-0x7FFFFFFFFFFFFFFF, x)
4462
4463    let x = 0
4464    let x /= 0
4465    call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x)
4466
4467    let x = 1
4468    let x %= 0
4469    call assert_equal(0, x)
4470
4471    let x = -1
4472    let x %= 0
4473    call assert_equal(0, x)
4474
4475    let x = 0
4476    let x %= 0
4477    call assert_equal(0, x)
4478
4479    " Test for string
4480    let x = 'str'
4481    let x .= 'ing'
4482    call assert_equal('string', x)
4483    let x += 1
4484    call assert_equal(1, x)
4485
4486    if has('float')
4487      " Test for float
4488      let x -= 1.5
4489      call assert_equal(-0.5, x)
4490      let x = 0.5
4491      let x += 4.5
4492      call assert_equal(5.0, x)
4493      let x -= 1.5
4494      call assert_equal(3.5, x)
4495      let x *= 3.0
4496      call assert_equal(10.5, x)
4497      let x /= 2.5
4498      call assert_equal(4.2, x)
4499      call assert_fails('let x %= 0.5', 'E734')
4500      call assert_fails('let x .= "f"', 'E734')
4501      let x = !3.14
4502      call assert_equal(0.0, x)
4503
4504      " integer and float operations
4505      let x = 1
4506      let x *= 2.1
4507      call assert_equal(2.1, x)
4508      let x = 1
4509      let x /= 0.25
4510      call assert_equal(4.0, x)
4511      let x = 1
4512      call assert_fails('let x %= 0.25', 'E734:')
4513      let x = 1
4514      call assert_fails('let x .= 0.25', 'E734:')
4515      let x = 1.0
4516      call assert_fails('let x += [1.1]', 'E734:')
4517    endif
4518
4519    " Test for environment variable
4520    let $FOO = 1
4521    call assert_fails('let $FOO += 1', 'E734')
4522    call assert_fails('let $FOO -= 1', 'E734')
4523    call assert_fails('let $FOO *= 1', 'E734')
4524    call assert_fails('let $FOO /= 1', 'E734')
4525    call assert_fails('let $FOO %= 1', 'E734')
4526    let $FOO .= 's'
4527    call assert_equal('1s', $FOO)
4528    unlet $FOO
4529
4530    " Test for option variable (type: number)
4531    let &scrolljump = 1
4532    let &scrolljump += 5
4533    call assert_equal(6, &scrolljump)
4534    let &scrolljump -= 2
4535    call assert_equal(4, &scrolljump)
4536    let &scrolljump *= 3
4537    call assert_equal(12, &scrolljump)
4538    let &scrolljump /= 2
4539    call assert_equal(6, &scrolljump)
4540    let &scrolljump %= 5
4541    call assert_equal(1, &scrolljump)
4542    call assert_fails('let &scrolljump .= "j"', 'E734')
4543    set scrolljump&vim
4544
4545    " Test for register
4546    let @/ = 1
4547    call assert_fails('let @/ += 1', 'E734')
4548    call assert_fails('let @/ -= 1', 'E734')
4549    call assert_fails('let @/ *= 1', 'E734')
4550    call assert_fails('let @/ /= 1', 'E734')
4551    call assert_fails('let @/ %= 1', 'E734')
4552    let @/ .= 's'
4553    call assert_equal('1s', @/)
4554    let @/ = ''
4555endfunc
4556
4557func Test_unlet_env()
4558  let $TESTVAR = 'yes'
4559  call assert_equal('yes', $TESTVAR)
4560  call assert_fails('lockvar $TESTVAR', 'E940')
4561  call assert_fails('unlockvar $TESTVAR', 'E940')
4562  call assert_equal('yes', $TESTVAR)
4563  if 0
4564    unlet $TESTVAR
4565  endif
4566  call assert_equal('yes', $TESTVAR)
4567  unlet $TESTVAR
4568  call assert_equal('', $TESTVAR)
4569endfunc
4570
4571func Test_refcount()
4572    " Immediate values
4573    call assert_equal(-1, test_refcount(1))
4574    call assert_equal(-1, test_refcount('s'))
4575    call assert_equal(-1, test_refcount(v:true))
4576    call assert_equal(0, test_refcount([]))
4577    call assert_equal(0, test_refcount({}))
4578    call assert_equal(0, test_refcount(0zff))
4579    call assert_equal(0, test_refcount({-> line('.')}))
4580    if has('float')
4581        call assert_equal(-1, test_refcount(0.1))
4582    endif
4583    if has('job')
4584        call assert_equal(0, test_refcount(job_start([&shell, &shellcmdflag, 'echo .'])))
4585    endif
4586
4587    " No refcount types
4588    let x = 1
4589    call assert_equal(-1, test_refcount(x))
4590    let x = 's'
4591    call assert_equal(-1, test_refcount(x))
4592    let x = v:true
4593    call assert_equal(-1, test_refcount(x))
4594    if has('float')
4595        let x = 0.1
4596        call assert_equal(-1, test_refcount(x))
4597    endif
4598
4599    " Check refcount
4600    let x = []
4601    call assert_equal(1, test_refcount(x))
4602
4603    let x = {}
4604    call assert_equal(1, x->test_refcount())
4605
4606    let x = 0zff
4607    call assert_equal(1, test_refcount(x))
4608
4609    let X = {-> line('.')}
4610    call assert_equal(1, test_refcount(X))
4611    let Y = X
4612    call assert_equal(2, test_refcount(X))
4613
4614    if has('job')
4615        let job = job_start([&shell, &shellcmdflag, 'echo .'])
4616        call assert_equal(1, test_refcount(job))
4617        call assert_equal(1, test_refcount(job_getchannel(job)))
4618        call assert_equal(1, test_refcount(job))
4619    endif
4620
4621    " Function arguments, copying and unassigning
4622    func ExprCheck(x, i)
4623        let i = a:i + 1
4624        call assert_equal(i, test_refcount(a:x))
4625        let Y = a:x
4626        call assert_equal(i + 1, test_refcount(a:x))
4627        call assert_equal(test_refcount(a:x), test_refcount(Y))
4628        let Y = 0
4629        call assert_equal(i, test_refcount(a:x))
4630    endfunc
4631    call ExprCheck([], 0)
4632    call ExprCheck({}, 0)
4633    call ExprCheck(0zff, 0)
4634    call ExprCheck({-> line('.')}, 0)
4635    if has('job')
4636	call ExprCheck(job, 1)
4637	call ExprCheck(job_getchannel(job), 1)
4638	call job_stop(job)
4639    endif
4640    delfunc ExprCheck
4641
4642    " Regarding function
4643    func Func(x) abort
4644        call assert_equal(2, test_refcount(function('Func')))
4645        call assert_equal(0, test_refcount(funcref('Func')))
4646    endfunc
4647    call assert_equal(1, test_refcount(function('Func')))
4648    call assert_equal(0, test_refcount(function('Func', [1])))
4649    call assert_equal(0, test_refcount(funcref('Func')))
4650    call assert_equal(0, test_refcount(funcref('Func', [1])))
4651    let X = function('Func')
4652    let Y = X
4653    call assert_equal(1, test_refcount(X))
4654    let X = function('Func', [1])
4655    let Y = X
4656    call assert_equal(2, test_refcount(X))
4657    let X = funcref('Func')
4658    let Y = X
4659    call assert_equal(2, test_refcount(X))
4660    let X = funcref('Func', [1])
4661    let Y = X
4662    call assert_equal(2, test_refcount(X))
4663    unlet X
4664    unlet Y
4665    call Func(1)
4666    delfunc Func
4667
4668    " Function with dict
4669    func DictFunc() dict
4670        call assert_equal(3, test_refcount(self))
4671    endfunc
4672    let d = {'Func': function('DictFunc')}
4673    call assert_equal(1, test_refcount(d))
4674    call assert_equal(0, test_refcount(d.Func))
4675    call d.Func()
4676    unlet d
4677    delfunc DictFunc
4678endfunc
4679
4680" Test for missing :endif, :endfor, :endwhile and :endtry           {{{1
4681func Test_missing_end()
4682  call writefile(['if 2 > 1', 'echo ">"'], 'Xscript')
4683  call assert_fails('source Xscript', 'E171:')
4684  call writefile(['for i in range(5)', 'echo i'], 'Xscript')
4685  call assert_fails('source Xscript', 'E170:')
4686  call writefile(['while v:true', 'echo "."'], 'Xscript')
4687  call assert_fails('source Xscript', 'E170:')
4688  call writefile(['try', 'echo "."'], 'Xscript')
4689  call assert_fails('source Xscript', 'E600:')
4690  call delete('Xscript')
4691
4692  " Using endfor with :while
4693  let caught_e732 = 0
4694  try
4695    while v:true
4696    endfor
4697  catch /E732:/
4698    let caught_e732 = 1
4699  endtry
4700  call assert_equal(1, caught_e732)
4701
4702  " Using endwhile with :for
4703  let caught_e733 = 0
4704  try
4705    for i in range(1)
4706    endwhile
4707  catch /E733:/
4708    let caught_e733 = 1
4709  endtry
4710  call assert_equal(1, caught_e733)
4711
4712  " Using endfunc with :if
4713  call assert_fails('exe "if 1 | endfunc | endif"', 'E193:')
4714
4715  " Missing 'in' in a :for statement
4716  call assert_fails('for i range(1) | endfor', 'E690:')
4717
4718  " Incorrect number of variables in for
4719  call assert_fails('for [i,] in range(3) | endfor', 'E475:')
4720endfunc
4721
4722" Test for deep nesting of if/for/while/try statements              {{{1
4723func Test_deep_nest()
4724  CheckRunVimInTerminal
4725
4726  let lines =<< trim [SCRIPT]
4727    " Deep nesting of if ... endif
4728    func Test1()
4729      let @a = join(repeat(['if v:true'], 51), "\n")
4730      let @a ..= "\n"
4731      let @a ..= join(repeat(['endif'], 51), "\n")
4732      @a
4733      let @a = ''
4734    endfunc
4735
4736    " Deep nesting of for ... endfor
4737    func Test2()
4738      let @a = join(repeat(['for i in [1]'], 51), "\n")
4739      let @a ..= "\n"
4740      let @a ..= join(repeat(['endfor'], 51), "\n")
4741      @a
4742      let @a = ''
4743    endfunc
4744
4745    " Deep nesting of while ... endwhile
4746    func Test3()
4747      let @a = join(repeat(['while v:true'], 51), "\n")
4748      let @a ..= "\n"
4749      let @a ..= join(repeat(['endwhile'], 51), "\n")
4750      @a
4751      let @a = ''
4752    endfunc
4753
4754    " Deep nesting of try ... endtry
4755    func Test4()
4756      let @a = join(repeat(['try'], 51), "\n")
4757      let @a ..= "\necho v:true\n"
4758      let @a ..= join(repeat(['endtry'], 51), "\n")
4759      @a
4760      let @a = ''
4761    endfunc
4762
4763    " Deep nesting of function ... endfunction
4764    func Test5()
4765      let @a = join(repeat(['function X()'], 51), "\n")
4766      let @a ..= "\necho v:true\n"
4767      let @a ..= join(repeat(['endfunction'], 51), "\n")
4768      @a
4769      let @a = ''
4770    endfunc
4771  [SCRIPT]
4772  call writefile(lines, 'Xscript')
4773
4774  let buf = RunVimInTerminal('-S Xscript', {'rows': 6})
4775
4776  " Deep nesting of if ... endif
4777  call term_sendkeys(buf, ":call Test1()\n")
4778  call TermWait(buf)
4779  call WaitForAssert({-> assert_match('^E579:', term_getline(buf, 5))})
4780
4781  " Deep nesting of for ... endfor
4782  call term_sendkeys(buf, ":call Test2()\n")
4783  call TermWait(buf)
4784  call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
4785
4786  " Deep nesting of while ... endwhile
4787  call term_sendkeys(buf, ":call Test3()\n")
4788  call TermWait(buf)
4789  call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
4790
4791  " Deep nesting of try ... endtry
4792  call term_sendkeys(buf, ":call Test4()\n")
4793  call TermWait(buf)
4794  call WaitForAssert({-> assert_match('^E601:', term_getline(buf, 5))})
4795
4796  " Deep nesting of function ... endfunction
4797  call term_sendkeys(buf, ":call Test5()\n")
4798  call TermWait(buf)
4799  call WaitForAssert({-> assert_match('^E1058:', term_getline(buf, 4))})
4800  call term_sendkeys(buf, "\<C-C>\n")
4801  call TermWait(buf)
4802
4803  "let l = ''
4804  "for i in range(1, 6)
4805  "  let l ..= term_getline(buf, i) . "\n"
4806  "endfor
4807  "call assert_report(l)
4808
4809  call StopVimInTerminal(buf)
4810  call delete('Xscript')
4811endfunc
4812
4813" Test for errors in converting to float from various types         {{{1
4814func Test_float_conversion_errors()
4815  if has('float')
4816    call assert_fails('let x = 4.0 % 2.0', 'E804')
4817    call assert_fails('echo 1.1[0]', 'E806')
4818    call assert_fails('echo sort([function("min"), 1], "f")', 'E891:')
4819    call assert_fails('echo 3.2 == "vim"', 'E892:')
4820    call assert_fails('echo sort([[], 1], "f")', 'E893:')
4821    call assert_fails('echo sort([{}, 1], "f")', 'E894:')
4822    call assert_fails('echo 3.2 == v:true', 'E362:')
4823    call assert_fails('echo 3.2 == v:none', 'E907:')
4824  endif
4825endfunc
4826
4827" invalid function names               {{{1
4828func Test_invalid_function_names()
4829  " function name not starting with capital
4830  let caught_e128 = 0
4831  try
4832    func! g:test()
4833      echo "test"
4834    endfunc
4835  catch /E128:/
4836    let caught_e128 = 1
4837  endtry
4838  call assert_equal(1, caught_e128)
4839
4840  " function name includes a colon
4841  let caught_e884 = 0
4842  try
4843    func! b:test()
4844      echo "test"
4845    endfunc
4846  catch /E884:/
4847    let caught_e884 = 1
4848  endtry
4849  call assert_equal(1, caught_e884)
4850
4851  " function name folowed by #
4852  let caught_e128 = 0
4853  try
4854    func! test2() "#
4855      echo "test2"
4856    endfunc
4857  catch /E128:/
4858    let caught_e128 = 1
4859  endtry
4860  call assert_equal(1, caught_e128)
4861
4862  " function name starting with/without "g:", buffer-local funcref.
4863  function! g:Foo(n)
4864    return 'called Foo(' . a:n . ')'
4865  endfunction
4866  let b:my_func = function('Foo')
4867  call assert_equal('called Foo(1)', b:my_func(1))
4868  call assert_equal('called Foo(2)', g:Foo(2))
4869  call assert_equal('called Foo(3)', Foo(3))
4870  delfunc g:Foo
4871
4872  " script-local function used in Funcref must exist.
4873  let lines =<< trim END
4874    func s:Testje()
4875      return "foo"
4876    endfunc
4877    let Bar = function('s:Testje')
4878    call assert_equal(0, exists('s:Testje'))
4879    call assert_equal(1, exists('*s:Testje'))
4880    call assert_equal(1, exists('Bar'))
4881    call assert_equal(1, exists('*Bar'))
4882  END
4883  call writefile(lines, 'Xscript')
4884  source Xscript
4885  call delete('Xscript')
4886endfunc
4887
4888" substring and variable name              {{{1
4889func Test_substring_var()
4890  let str = 'abcdef'
4891  let n = 3
4892  call assert_equal('def', str[n:])
4893  call assert_equal('abcd', str[:n])
4894  call assert_equal('d', str[n:n])
4895  unlet n
4896  let nn = 3
4897  call assert_equal('def', str[nn:])
4898  call assert_equal('abcd', str[:nn])
4899  call assert_equal('d', str[nn:nn])
4900  unlet nn
4901  let b:nn = 4
4902  call assert_equal('ef', str[b:nn:])
4903  call assert_equal('abcde', str[:b:nn])
4904  call assert_equal('e', str[b:nn:b:nn])
4905  unlet b:nn
4906endfunc
4907
4908" Test using s: with a typed command              {{{1
4909func Test_typed_script_var()
4910  CheckRunVimInTerminal
4911
4912  let buf = RunVimInTerminal('', {'rows': 6})
4913
4914  " Deep nesting of if ... endif
4915  call term_sendkeys(buf, ":echo get(s:, 'foo', 'x')\n")
4916  call TermWait(buf)
4917  call WaitForAssert({-> assert_match('^E116:', term_getline(buf, 5))})
4918
4919  call StopVimInTerminal(buf)
4920endfunc
4921
4922"-------------------------------------------------------------------------------
4923" Modelines								    {{{1
4924" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
4925"-------------------------------------------------------------------------------
4926