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 87   using (expr) ? funcref : funcref				    {{{1
2768"
2769"	    Vim needs to correctly parse the funcref and even when it does
2770"	    not execute the funcref, it needs to consume the trailing ()
2771"-------------------------------------------------------------------------------
2772
2773func Add2(x1, x2)
2774  return a:x1 + a:x2
2775endfu
2776
2777func GetStr()
2778  return "abcdefghijklmnopqrstuvwxyp"
2779endfu
2780
2781func Test_funcref_with_condexpr()
2782  call assert_equal(5, function('Add2')(2,3))
2783
2784  call assert_equal(3, 1 ? function('Add2')(1,2) : function('Add2')(2,3))
2785  call assert_equal(5, 0 ? function('Add2')(1,2) : function('Add2')(2,3))
2786  " Make sure, GetStr() still works.
2787  call assert_equal('abcdefghijk', GetStr()[0:10])
2788endfunc
2789
2790" Test 90:  Recognizing {} in variable name.			    {{{1
2791"-------------------------------------------------------------------------------
2792
2793func Test_curlies()
2794    let s:var = 66
2795    let ns = 's'
2796    call assert_equal(66, {ns}:var)
2797
2798    let g:a = {}
2799    let g:b = 't'
2800    let g:a[g:b] = 77
2801    call assert_equal(77, g:a['t'])
2802endfunc
2803
2804"-------------------------------------------------------------------------------
2805" Test 91:  using type().					    {{{1
2806"-------------------------------------------------------------------------------
2807
2808func Test_type()
2809    call assert_equal(0, type(0))
2810    call assert_equal(1, type(""))
2811    call assert_equal(2, type(function("tr")))
2812    call assert_equal(2, type(function("tr", [8])))
2813    call assert_equal(3, type([]))
2814    call assert_equal(4, type({}))
2815    if has('float')
2816      call assert_equal(5, type(0.0))
2817    endif
2818    call assert_equal(6, type(v:false))
2819    call assert_equal(6, type(v:true))
2820    call assert_equal(7, type(v:none))
2821    call assert_equal(7, type(v:null))
2822    call assert_equal(8, v:t_job)
2823    call assert_equal(9, v:t_channel)
2824    call assert_equal(v:t_number, type(0))
2825    call assert_equal(v:t_string, type(""))
2826    call assert_equal(v:t_func, type(function("tr")))
2827    call assert_equal(v:t_func, type(function("tr", [8])))
2828    call assert_equal(v:t_list, type([]))
2829    call assert_equal(v:t_dict, type({}))
2830    if has('float')
2831      call assert_equal(v:t_float, type(0.0))
2832    endif
2833    call assert_equal(v:t_bool, type(v:false))
2834    call assert_equal(v:t_bool, type(v:true))
2835    call assert_equal(v:t_none, type(v:none))
2836    call assert_equal(v:t_none, type(v:null))
2837    call assert_equal(v:t_string, type(test_null_string()))
2838    call assert_equal(v:t_func, type(test_null_function()))
2839    call assert_equal(v:t_func, type(test_null_partial()))
2840    call assert_equal(v:t_list, type(test_null_list()))
2841    call assert_equal(v:t_dict, type(test_null_dict()))
2842    if has('job')
2843      call assert_equal(v:t_job, type(test_null_job()))
2844    endif
2845    if has('channel')
2846      call assert_equal(v:t_channel, type(test_null_channel()))
2847    endif
2848    call assert_equal(v:t_blob, type(test_null_blob()))
2849
2850    call assert_fails("call type(test_void())", 'E685:')
2851    call assert_fails("call type(test_unknown())", 'E685:')
2852
2853    call assert_equal(0, 0 + v:false)
2854    call assert_equal(1, 0 + v:true)
2855    call assert_equal(0, 0 + v:none)
2856    call assert_equal(0, 0 + v:null)
2857
2858    call assert_equal('v:false', '' . v:false)
2859    call assert_equal('v:true', '' . v:true)
2860    call assert_equal('v:none', '' . v:none)
2861    call assert_equal('v:null', '' . v:null)
2862
2863    call assert_true(v:false == 0)
2864    call assert_false(v:false != 0)
2865    call assert_true(v:true == 1)
2866    call assert_false(v:true != 1)
2867    call assert_false(v:true == v:false)
2868    call assert_true(v:true != v:false)
2869
2870    call assert_true(v:null == 0)
2871    call assert_false(v:null != 0)
2872    call assert_true(v:none == 0)
2873    call assert_false(v:none != 0)
2874
2875    call assert_true(v:false is v:false)
2876    call assert_true(v:true is v:true)
2877    call assert_true(v:none is v:none)
2878    call assert_true(v:null is v:null)
2879
2880    call assert_false(v:false isnot v:false)
2881    call assert_false(v:true isnot v:true)
2882    call assert_false(v:none isnot v:none)
2883    call assert_false(v:null isnot v:null)
2884
2885    call assert_false(v:false is 0)
2886    call assert_false(v:true is 1)
2887    call assert_false(v:true is v:false)
2888    call assert_false(v:none is 0)
2889    call assert_false(v:null is 0)
2890    call assert_false(v:null is v:none)
2891
2892    call assert_true(v:false isnot 0)
2893    call assert_true(v:true isnot 1)
2894    call assert_true(v:true isnot v:false)
2895    call assert_true(v:none isnot 0)
2896    call assert_true(v:null isnot 0)
2897    call assert_true(v:null isnot v:none)
2898
2899    call assert_equal(v:false, eval(string(v:false)))
2900    call assert_equal(v:true, eval(string(v:true)))
2901    call assert_equal(v:none, eval(string(v:none)))
2902    call assert_equal(v:null, eval(string(v:null)))
2903
2904    call assert_equal(v:false, copy(v:false))
2905    call assert_equal(v:true, copy(v:true))
2906    call assert_equal(v:none, copy(v:none))
2907    call assert_equal(v:null, copy(v:null))
2908
2909    call assert_equal([v:false], deepcopy([v:false]))
2910    call assert_equal([v:true], deepcopy([v:true]))
2911    call assert_equal([v:none], deepcopy([v:none]))
2912    call assert_equal([v:null], deepcopy([v:null]))
2913
2914    call assert_true(empty(v:false))
2915    call assert_false(empty(v:true))
2916    call assert_true(empty(v:null))
2917    call assert_true(empty(v:none))
2918
2919    func ChangeYourMind()
2920	try
2921	    return v:true
2922	finally
2923	    return 'something else'
2924	endtry
2925    endfunc
2926
2927    call ChangeYourMind()
2928endfunc
2929
2930"-------------------------------------------------------------------------------
2931" Test 92:  skipping code					    {{{1
2932"-------------------------------------------------------------------------------
2933
2934func Test_skip()
2935    let Fn = function('Test_type')
2936    call assert_false(0 && Fn[1])
2937    call assert_false(0 && string(Fn))
2938    call assert_false(0 && len(Fn))
2939    let l = []
2940    call assert_false(0 && l[1])
2941    call assert_false(0 && string(l))
2942    call assert_false(0 && len(l))
2943    let f = 1.0
2944    call assert_false(0 && f[1])
2945    call assert_false(0 && string(f))
2946    call assert_false(0 && len(f))
2947    let sp = v:null
2948    call assert_false(0 && sp[1])
2949    call assert_false(0 && string(sp))
2950    call assert_false(0 && len(sp))
2951
2952endfunc
2953
2954"-------------------------------------------------------------------------------
2955" Test 93:  :echo and string()					    {{{1
2956"-------------------------------------------------------------------------------
2957
2958func Test_echo_and_string()
2959    " String
2960    let a = 'foo bar'
2961    redir => result
2962    echo a
2963    echo string(a)
2964    redir END
2965    let l = split(result, "\n")
2966    call assert_equal(["foo bar",
2967		     \ "'foo bar'"], l)
2968
2969    " Float
2970    if has('float')
2971	let a = -1.2e0
2972	redir => result
2973	echo a
2974	echo string(a)
2975	redir END
2976	let l = split(result, "\n")
2977	call assert_equal(["-1.2",
2978			 \ "-1.2"], l)
2979    endif
2980
2981    " Funcref
2982    redir => result
2983    echo function('string')
2984    echo string(function('string'))
2985    redir END
2986    let l = split(result, "\n")
2987    call assert_equal(["string",
2988		     \ "function('string')"], l)
2989
2990    " Recursive dictionary
2991    let a = {}
2992    let a["a"] = a
2993    redir => result
2994    echo a
2995    echo string(a)
2996    redir END
2997    let l = split(result, "\n")
2998    call assert_equal(["{'a': {...}}",
2999		     \ "{'a': {...}}"], l)
3000
3001    " Recursive list
3002    let a = [0]
3003    let a[0] = a
3004    redir => result
3005    echo a
3006    echo string(a)
3007    redir END
3008    let l = split(result, "\n")
3009    call assert_equal(["[[...]]",
3010		     \ "[[...]]"], l)
3011
3012    " Empty dictionaries in a list
3013    let a = {}
3014    redir => result
3015    echo [a, a, a]
3016    echo string([a, a, a])
3017    redir END
3018    let l = split(result, "\n")
3019    call assert_equal(["[{}, {}, {}]",
3020		     \ "[{}, {}, {}]"], l)
3021
3022    " Empty dictionaries in a dictionary
3023    let a = {}
3024    let b = {"a": a, "b": a}
3025    redir => result
3026    echo b
3027    echo string(b)
3028    redir END
3029    let l = split(result, "\n")
3030    call assert_equal(["{'a': {}, 'b': {}}",
3031		     \ "{'a': {}, 'b': {}}"], l)
3032
3033    " Empty lists in a list
3034    let a = []
3035    redir => result
3036    echo [a, a, a]
3037    echo string([a, a, a])
3038    redir END
3039    let l = split(result, "\n")
3040    call assert_equal(["[[], [], []]",
3041		     \ "[[], [], []]"], l)
3042
3043    " Empty lists in a dictionary
3044    let a = []
3045    let b = {"a": a, "b": a}
3046    redir => result
3047    echo b
3048    echo string(b)
3049    redir END
3050    let l = split(result, "\n")
3051    call assert_equal(["{'a': [], 'b': []}",
3052		     \ "{'a': [], 'b': []}"], l)
3053
3054    " Dictionaries in a list
3055    let a = {"one": "yes", "two": "yes", "three": "yes"}
3056    redir => result
3057    echo [a, a, a]
3058    echo string([a, a, a])
3059    redir END
3060    let l = split(result, "\n")
3061    call assert_equal(["[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {...}, {...}]",
3062		     \ "[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}]"], l)
3063
3064    " Dictionaries in a dictionary
3065    let a = {"one": "yes", "two": "yes", "three": "yes"}
3066    let b = {"a": a, "b": a}
3067    redir => result
3068    echo b
3069    echo string(b)
3070    redir END
3071    let l = split(result, "\n")
3072    call assert_equal(["{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {...}}",
3073		     \ "{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {'one': 'yes', 'two': 'yes', 'three': 'yes'}}"], l)
3074
3075    " Lists in a list
3076    let a = [1, 2, 3]
3077    redir => result
3078    echo [a, a, a]
3079    echo string([a, a, a])
3080    redir END
3081    let l = split(result, "\n")
3082    call assert_equal(["[[1, 2, 3], [...], [...]]",
3083		     \ "[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"], l)
3084
3085    " Lists in a dictionary
3086    let a = [1, 2, 3]
3087    let b = {"a": a, "b": a}
3088    redir => result
3089    echo b
3090    echo string(b)
3091    redir END
3092    let l = split(result, "\n")
3093    call assert_equal(["{'a': [1, 2, 3], 'b': [...]}",
3094		     \ "{'a': [1, 2, 3], 'b': [1, 2, 3]}"], l)
3095
3096    call assert_fails('echo &:', 'E112:')
3097    call assert_fails('echo &g:', 'E112:')
3098    call assert_fails('echo &l:', 'E112:')
3099
3100endfunc
3101
3102"-------------------------------------------------------------------------------
3103" Test 94:  64-bit Numbers					    {{{1
3104"-------------------------------------------------------------------------------
3105
3106func Test_num64()
3107    call assert_notequal( 4294967296, 0)
3108    call assert_notequal(-4294967296, 0)
3109    call assert_equal( 4294967296,  0xFFFFffff + 1)
3110    call assert_equal(-4294967296, -0xFFFFffff - 1)
3111
3112    call assert_equal( 9223372036854775807,  1 / 0)
3113    call assert_equal(-9223372036854775807, -1 / 0)
3114    call assert_equal(-9223372036854775807 - 1,  0 / 0)
3115
3116    if has('float')
3117      call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150))
3118      call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150))
3119    endif
3120
3121    let rng = range(0xFFFFffff, 0x100000001)
3122    call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng)
3123    call assert_equal(0x100000001, max(rng))
3124    call assert_equal(0xFFFFffff, min(rng))
3125    call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N'))
3126endfunc
3127
3128"-------------------------------------------------------------------------------
3129" Test 95:  lines of :append, :change, :insert			    {{{1
3130"-------------------------------------------------------------------------------
3131
3132function! DefineFunction(name, body)
3133    let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n")
3134    exec func
3135endfunction
3136
3137func Test_script_lines()
3138    " :append
3139    try
3140	call DefineFunction('T_Append', [
3141		    \ 'append',
3142		    \ 'py <<EOS',
3143		    \ '.',
3144		    \ ])
3145    catch
3146	call assert_report("Can't define function")
3147    endtry
3148    try
3149	call DefineFunction('T_Append', [
3150		    \ 'append',
3151		    \ 'abc',
3152		    \ ])
3153	call assert_report("Shouldn't be able to define function")
3154    catch
3155	call assert_exception('Vim(function):E126: Missing :endfunction')
3156    endtry
3157
3158    " :change
3159    try
3160	call DefineFunction('T_Change', [
3161		    \ 'change',
3162		    \ 'py <<EOS',
3163		    \ '.',
3164		    \ ])
3165    catch
3166	call assert_report("Can't define function")
3167    endtry
3168    try
3169	call DefineFunction('T_Change', [
3170		    \ 'change',
3171		    \ 'abc',
3172		    \ ])
3173	call assert_report("Shouldn't be able to define function")
3174    catch
3175	call assert_exception('Vim(function):E126: Missing :endfunction')
3176    endtry
3177
3178    " :insert
3179    try
3180	call DefineFunction('T_Insert', [
3181		    \ 'insert',
3182		    \ 'py <<EOS',
3183		    \ '.',
3184		    \ ])
3185    catch
3186	call assert_report("Can't define function")
3187    endtry
3188    try
3189	call DefineFunction('T_Insert', [
3190		    \ 'insert',
3191		    \ 'abc',
3192		    \ ])
3193	call assert_report("Shouldn't be able to define function")
3194    catch
3195	call assert_exception('Vim(function):E126: Missing :endfunction')
3196    endtry
3197endfunc
3198
3199"-------------------------------------------------------------------------------
3200" Test 96:  line continuation						    {{{1
3201"
3202"	    Undefined behavior was detected by ubsan with line continuation
3203"	    after an empty line.
3204"-------------------------------------------------------------------------------
3205func Test_script_emty_line_continuation()
3206
3207    \
3208endfunc
3209
3210"-------------------------------------------------------------------------------
3211" Test 97:  bitwise functions						    {{{1
3212"-------------------------------------------------------------------------------
3213func Test_bitwise_functions()
3214    " and
3215    call assert_equal(127, and(127, 127))
3216    call assert_equal(16, and(127, 16))
3217    eval 127->and(16)->assert_equal(16)
3218    call assert_equal(0, and(127, 128))
3219    call assert_fails("call and([], 1)", 'E745:')
3220    call assert_fails("call and({}, 1)", 'E728:')
3221    if has('float')
3222      call assert_fails("call and(1.0, 1)", 'E805:')
3223      call assert_fails("call and(1, 1.0)", 'E805:')
3224    endif
3225    call assert_fails("call and(1, [])", 'E745:')
3226    call assert_fails("call and(1, {})", 'E728:')
3227    " or
3228    call assert_equal(23, or(16, 7))
3229    call assert_equal(15, or(8, 7))
3230    eval 8->or(7)->assert_equal(15)
3231    call assert_equal(123, or(0, 123))
3232    call assert_fails("call or([], 1)", 'E745:')
3233    call assert_fails("call or({}, 1)", 'E728:')
3234    if has('float')
3235      call assert_fails("call or(1.0, 1)", 'E805:')
3236      call assert_fails("call or(1, 1.0)", 'E805:')
3237    endif
3238    call assert_fails("call or(1, [])", 'E745:')
3239    call assert_fails("call or(1, {})", 'E728:')
3240    " xor
3241    call assert_equal(0, xor(127, 127))
3242    call assert_equal(111, xor(127, 16))
3243    eval 127->xor(16)->assert_equal(111)
3244    call assert_equal(255, xor(127, 128))
3245    if has('float')
3246      call assert_fails("call xor(1.0, 1)", 'E805:')
3247      call assert_fails("call xor(1, 1.0)", 'E805:')
3248    endif
3249    call assert_fails("call xor([], 1)", 'E745:')
3250    call assert_fails("call xor({}, 1)", 'E728:')
3251    call assert_fails("call xor(1, [])", 'E745:')
3252    call assert_fails("call xor(1, {})", 'E728:')
3253    " invert
3254    call assert_equal(65408, and(invert(127), 65535))
3255    eval 127->invert()->and(65535)->assert_equal(65408)
3256    call assert_equal(65519, and(invert(16), 65535))
3257    call assert_equal(65407, and(invert(128), 65535))
3258    if has('float')
3259      call assert_fails("call invert(1.0)", 'E805:')
3260    endif
3261    call assert_fails("call invert([])", 'E745:')
3262    call assert_fails("call invert({})", 'E728:')
3263endfunc
3264
3265" Test using bang after user command				    {{{1
3266func Test_user_command_with_bang()
3267    command -bang Nieuw let nieuw = 1
3268    Ni!
3269    call assert_equal(1, nieuw)
3270    unlet nieuw
3271    delcommand Nieuw
3272endfunc
3273
3274func Test_script_expand_sfile()
3275  let lines =<< trim END
3276    func s:snr()
3277      return expand('<sfile>')
3278    endfunc
3279    let g:result = s:snr()
3280  END
3281  call writefile(lines, 'Xexpand')
3282  source Xexpand
3283  call assert_match('<SNR>\d\+_snr', g:result)
3284  source Xexpand
3285  call assert_match('<SNR>\d\+_snr', g:result)
3286
3287  call delete('Xexpand')
3288  unlet g:result
3289endfunc
3290
3291func Test_compound_assignment_operators()
3292    " Test for number
3293    let x = 1
3294    let x += 10
3295    call assert_equal(11, x)
3296    let x -= 5
3297    call assert_equal(6, x)
3298    let x *= 4
3299    call assert_equal(24, x)
3300    let x /= 3
3301    call assert_equal(8, x)
3302    let x %= 3
3303    call assert_equal(2, x)
3304    let x .= 'n'
3305    call assert_equal('2n', x)
3306
3307    " Test special cases: division or modulus with 0.
3308    let x = 1
3309    let x /= 0
3310    call assert_equal(0x7FFFFFFFFFFFFFFF, x)
3311
3312    let x = -1
3313    let x /= 0
3314    call assert_equal(-0x7FFFFFFFFFFFFFFF, x)
3315
3316    let x = 0
3317    let x /= 0
3318    call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x)
3319
3320    let x = 1
3321    let x %= 0
3322    call assert_equal(0, x)
3323
3324    let x = -1
3325    let x %= 0
3326    call assert_equal(0, x)
3327
3328    let x = 0
3329    let x %= 0
3330    call assert_equal(0, x)
3331
3332    " Test for string
3333    let x = 'str'
3334    let x .= 'ing'
3335    call assert_equal('string', x)
3336    let x += 1
3337    call assert_equal(1, x)
3338
3339    if has('float')
3340      " Test for float
3341      let x -= 1.5
3342      call assert_equal(-0.5, x)
3343      let x = 0.5
3344      let x += 4.5
3345      call assert_equal(5.0, x)
3346      let x -= 1.5
3347      call assert_equal(3.5, x)
3348      let x *= 3.0
3349      call assert_equal(10.5, x)
3350      let x /= 2.5
3351      call assert_equal(4.2, x)
3352      call assert_fails('let x %= 0.5', 'E734')
3353      call assert_fails('let x .= "f"', 'E734')
3354      let x = !3.14
3355      call assert_equal(0.0, x)
3356
3357      " integer and float operations
3358      let x = 1
3359      let x *= 2.1
3360      call assert_equal(2.1, x)
3361      let x = 1
3362      let x /= 0.25
3363      call assert_equal(4.0, x)
3364      let x = 1
3365      call assert_fails('let x %= 0.25', 'E734:')
3366      let x = 1
3367      call assert_fails('let x .= 0.25', 'E734:')
3368      let x = 1.0
3369      call assert_fails('let x += [1.1]', 'E734:')
3370    endif
3371
3372    " Test for environment variable
3373    let $FOO = 1
3374    call assert_fails('let $FOO += 1', 'E734')
3375    call assert_fails('let $FOO -= 1', 'E734')
3376    call assert_fails('let $FOO *= 1', 'E734')
3377    call assert_fails('let $FOO /= 1', 'E734')
3378    call assert_fails('let $FOO %= 1', 'E734')
3379    let $FOO .= 's'
3380    call assert_equal('1s', $FOO)
3381    unlet $FOO
3382
3383    " Test for option variable (type: number)
3384    let &scrolljump = 1
3385    let &scrolljump += 5
3386    call assert_equal(6, &scrolljump)
3387    let &scrolljump -= 2
3388    call assert_equal(4, &scrolljump)
3389    let &scrolljump *= 3
3390    call assert_equal(12, &scrolljump)
3391    let &scrolljump /= 2
3392    call assert_equal(6, &scrolljump)
3393    let &scrolljump %= 5
3394    call assert_equal(1, &scrolljump)
3395    call assert_fails('let &scrolljump .= "j"', 'E734')
3396    set scrolljump&vim
3397
3398    " Test for register
3399    let @/ = 1
3400    call assert_fails('let @/ += 1', 'E734')
3401    call assert_fails('let @/ -= 1', 'E734')
3402    call assert_fails('let @/ *= 1', 'E734')
3403    call assert_fails('let @/ /= 1', 'E734')
3404    call assert_fails('let @/ %= 1', 'E734')
3405    let @/ .= 's'
3406    call assert_equal('1s', @/)
3407    let @/ = ''
3408endfunc
3409
3410func Test_unlet_env()
3411  let $TESTVAR = 'yes'
3412  call assert_equal('yes', $TESTVAR)
3413  call assert_fails('lockvar $TESTVAR', 'E940')
3414  call assert_fails('unlockvar $TESTVAR', 'E940')
3415  call assert_equal('yes', $TESTVAR)
3416  if 0
3417    unlet $TESTVAR
3418  endif
3419  call assert_equal('yes', $TESTVAR)
3420  unlet $TESTVAR
3421  call assert_equal('', $TESTVAR)
3422endfunc
3423
3424func Test_refcount()
3425    " Immediate values
3426    call assert_equal(-1, test_refcount(1))
3427    call assert_equal(-1, test_refcount('s'))
3428    call assert_equal(-1, test_refcount(v:true))
3429    call assert_equal(0, test_refcount([]))
3430    call assert_equal(0, test_refcount({}))
3431    call assert_equal(0, test_refcount(0zff))
3432    call assert_equal(0, test_refcount({-> line('.')}))
3433    if has('float')
3434        call assert_equal(-1, test_refcount(0.1))
3435    endif
3436    if has('job')
3437        call assert_equal(0, test_refcount(job_start([&shell, &shellcmdflag, 'echo .'])))
3438    endif
3439
3440    " No refcount types
3441    let x = 1
3442    call assert_equal(-1, test_refcount(x))
3443    let x = 's'
3444    call assert_equal(-1, test_refcount(x))
3445    let x = v:true
3446    call assert_equal(-1, test_refcount(x))
3447    if has('float')
3448        let x = 0.1
3449        call assert_equal(-1, test_refcount(x))
3450    endif
3451
3452    " Check refcount
3453    let x = []
3454    call assert_equal(1, test_refcount(x))
3455
3456    let x = {}
3457    call assert_equal(1, x->test_refcount())
3458
3459    let x = 0zff
3460    call assert_equal(1, test_refcount(x))
3461
3462    let X = {-> line('.')}
3463    call assert_equal(1, test_refcount(X))
3464    let Y = X
3465    call assert_equal(2, test_refcount(X))
3466
3467    if has('job')
3468        let job = job_start([&shell, &shellcmdflag, 'echo .'])
3469        call assert_equal(1, test_refcount(job))
3470        call assert_equal(1, test_refcount(job_getchannel(job)))
3471        call assert_equal(1, test_refcount(job))
3472    endif
3473
3474    " Function arguments, copying and unassigning
3475    func ExprCheck(x, i)
3476        let i = a:i + 1
3477        call assert_equal(i, test_refcount(a:x))
3478        let Y = a:x
3479        call assert_equal(i + 1, test_refcount(a:x))
3480        call assert_equal(test_refcount(a:x), test_refcount(Y))
3481        let Y = 0
3482        call assert_equal(i, test_refcount(a:x))
3483    endfunc
3484    call ExprCheck([], 0)
3485    call ExprCheck({}, 0)
3486    call ExprCheck(0zff, 0)
3487    call ExprCheck({-> line('.')}, 0)
3488    if has('job')
3489	call ExprCheck(job, 1)
3490	call ExprCheck(job_getchannel(job), 1)
3491	call job_stop(job)
3492    endif
3493    delfunc ExprCheck
3494
3495    " Regarding function
3496    func Func(x) abort
3497        call assert_equal(2, test_refcount(function('Func')))
3498        call assert_equal(0, test_refcount(funcref('Func')))
3499    endfunc
3500    call assert_equal(1, test_refcount(function('Func')))
3501    call assert_equal(0, test_refcount(function('Func', [1])))
3502    call assert_equal(0, test_refcount(funcref('Func')))
3503    call assert_equal(0, test_refcount(funcref('Func', [1])))
3504    let X = function('Func')
3505    let Y = X
3506    call assert_equal(1, test_refcount(X))
3507    let X = function('Func', [1])
3508    let Y = X
3509    call assert_equal(2, test_refcount(X))
3510    let X = funcref('Func')
3511    let Y = X
3512    call assert_equal(2, test_refcount(X))
3513    let X = funcref('Func', [1])
3514    let Y = X
3515    call assert_equal(2, test_refcount(X))
3516    unlet X
3517    unlet Y
3518    call Func(1)
3519    delfunc Func
3520
3521    " Function with dict
3522    func DictFunc() dict
3523        call assert_equal(3, test_refcount(self))
3524    endfunc
3525    let d = {'Func': function('DictFunc')}
3526    call assert_equal(1, test_refcount(d))
3527    call assert_equal(0, test_refcount(d.Func))
3528    call d.Func()
3529    unlet d
3530    delfunc DictFunc
3531endfunc
3532
3533" Test for missing :endif, :endfor, :endwhile and :endtry           {{{1
3534func Test_missing_end()
3535  call writefile(['if 2 > 1', 'echo ">"'], 'Xscript')
3536  call assert_fails('source Xscript', 'E171:')
3537  call writefile(['for i in range(5)', 'echo i'], 'Xscript')
3538  call assert_fails('source Xscript', 'E170:')
3539  call writefile(['while v:true', 'echo "."'], 'Xscript')
3540  call assert_fails('source Xscript', 'E170:')
3541  call writefile(['try', 'echo "."'], 'Xscript')
3542  call assert_fails('source Xscript', 'E600:')
3543  call delete('Xscript')
3544
3545  " Using endfor with :while
3546  let caught_e732 = 0
3547  try
3548    while v:true
3549    endfor
3550  catch /E732:/
3551    let caught_e732 = 1
3552  endtry
3553  call assert_equal(1, caught_e732)
3554
3555  " Using endwhile with :for
3556  let caught_e733 = 0
3557  try
3558    for i in range(1)
3559    endwhile
3560  catch /E733:/
3561    let caught_e733 = 1
3562  endtry
3563  call assert_equal(1, caught_e733)
3564
3565  " Using endfunc with :if
3566  call assert_fails('exe "if 1 | endfunc | endif"', 'E193:')
3567
3568  " Missing 'in' in a :for statement
3569  call assert_fails('for i range(1) | endfor', 'E690:')
3570
3571  " Incorrect number of variables in for
3572  call assert_fails('for [i,] in range(3) | endfor', 'E475:')
3573endfunc
3574
3575" Test for deep nesting of if/for/while/try statements              {{{1
3576func Test_deep_nest()
3577  CheckRunVimInTerminal
3578
3579  let lines =<< trim [SCRIPT]
3580    " Deep nesting of if ... endif
3581    func Test1()
3582      let @a = join(repeat(['if v:true'], 51), "\n")
3583      let @a ..= "\n"
3584      let @a ..= join(repeat(['endif'], 51), "\n")
3585      @a
3586      let @a = ''
3587    endfunc
3588
3589    " Deep nesting of for ... endfor
3590    func Test2()
3591      let @a = join(repeat(['for i in [1]'], 51), "\n")
3592      let @a ..= "\n"
3593      let @a ..= join(repeat(['endfor'], 51), "\n")
3594      @a
3595      let @a = ''
3596    endfunc
3597
3598    " Deep nesting of while ... endwhile
3599    func Test3()
3600      let @a = join(repeat(['while v:true'], 51), "\n")
3601      let @a ..= "\n"
3602      let @a ..= join(repeat(['endwhile'], 51), "\n")
3603      @a
3604      let @a = ''
3605    endfunc
3606
3607    " Deep nesting of try ... endtry
3608    func Test4()
3609      let @a = join(repeat(['try'], 51), "\n")
3610      let @a ..= "\necho v:true\n"
3611      let @a ..= join(repeat(['endtry'], 51), "\n")
3612      @a
3613      let @a = ''
3614    endfunc
3615
3616    " Deep nesting of function ... endfunction
3617    func Test5()
3618      let @a = join(repeat(['function X()'], 51), "\n")
3619      let @a ..= "\necho v:true\n"
3620      let @a ..= join(repeat(['endfunction'], 51), "\n")
3621      @a
3622      let @a = ''
3623    endfunc
3624  [SCRIPT]
3625  call writefile(lines, 'Xscript')
3626
3627  let buf = RunVimInTerminal('-S Xscript', {'rows': 6})
3628
3629  " Deep nesting of if ... endif
3630  call term_sendkeys(buf, ":call Test1()\n")
3631  call TermWait(buf)
3632  call WaitForAssert({-> assert_match('^E579:', term_getline(buf, 5))})
3633
3634  " Deep nesting of for ... endfor
3635  call term_sendkeys(buf, ":call Test2()\n")
3636  call TermWait(buf)
3637  call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
3638
3639  " Deep nesting of while ... endwhile
3640  call term_sendkeys(buf, ":call Test3()\n")
3641  call TermWait(buf)
3642  call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
3643
3644  " Deep nesting of try ... endtry
3645  call term_sendkeys(buf, ":call Test4()\n")
3646  call TermWait(buf)
3647  call WaitForAssert({-> assert_match('^E601:', term_getline(buf, 5))})
3648
3649  " Deep nesting of function ... endfunction
3650  call term_sendkeys(buf, ":call Test5()\n")
3651  call TermWait(buf)
3652  call WaitForAssert({-> assert_match('^E1058:', term_getline(buf, 4))})
3653  call term_sendkeys(buf, "\<C-C>\n")
3654  call TermWait(buf)
3655
3656  "let l = ''
3657  "for i in range(1, 6)
3658  "  let l ..= term_getline(buf, i) . "\n"
3659  "endfor
3660  "call assert_report(l)
3661
3662  call StopVimInTerminal(buf)
3663  call delete('Xscript')
3664endfunc
3665
3666" Test for errors in converting to float from various types         {{{1
3667func Test_float_conversion_errors()
3668  if has('float')
3669    call assert_fails('let x = 4.0 % 2.0', 'E804')
3670    call assert_fails('echo 1.1[0]', 'E806')
3671    call assert_fails('echo sort([function("min"), 1], "f")', 'E891:')
3672    call assert_fails('echo 3.2 == "vim"', 'E892:')
3673    call assert_fails('echo sort([[], 1], "f")', 'E893:')
3674    call assert_fails('echo sort([{}, 1], "f")', 'E894:')
3675    call assert_fails('echo 3.2 == v:true', 'E362:')
3676    call assert_fails('echo 3.2 == v:none', 'E907:')
3677  endif
3678endfunc
3679
3680" invalid function names               {{{1
3681func Test_invalid_function_names()
3682  " function name not starting with capital
3683  let caught_e128 = 0
3684  try
3685    func! g:test()
3686      echo "test"
3687    endfunc
3688  catch /E128:/
3689    let caught_e128 = 1
3690  endtry
3691  call assert_equal(1, caught_e128)
3692
3693  " function name includes a colon
3694  let caught_e884 = 0
3695  try
3696    func! b:test()
3697      echo "test"
3698    endfunc
3699  catch /E884:/
3700    let caught_e884 = 1
3701  endtry
3702  call assert_equal(1, caught_e884)
3703
3704  " function name folowed by #
3705  let caught_e128 = 0
3706  try
3707    func! test2() "#
3708      echo "test2"
3709    endfunc
3710  catch /E128:/
3711    let caught_e128 = 1
3712  endtry
3713  call assert_equal(1, caught_e128)
3714
3715  " function name starting with/without "g:", buffer-local funcref.
3716  function! g:Foo(n)
3717    return 'called Foo(' . a:n . ')'
3718  endfunction
3719  let b:my_func = function('Foo')
3720  call assert_equal('called Foo(1)', b:my_func(1))
3721  call assert_equal('called Foo(2)', g:Foo(2))
3722  call assert_equal('called Foo(3)', Foo(3))
3723  delfunc g:Foo
3724
3725  " script-local function used in Funcref must exist.
3726  let lines =<< trim END
3727    func s:Testje()
3728      return "foo"
3729    endfunc
3730    let Bar = function('s:Testje')
3731    call assert_equal(0, exists('s:Testje'))
3732    call assert_equal(1, exists('*s:Testje'))
3733    call assert_equal(1, exists('Bar'))
3734    call assert_equal(1, exists('*Bar'))
3735  END
3736  call writefile(lines, 'Xscript')
3737  source Xscript
3738  call delete('Xscript')
3739endfunc
3740
3741" substring and variable name              {{{1
3742func Test_substring_var()
3743  let str = 'abcdef'
3744  let n = 3
3745  call assert_equal('def', str[n:])
3746  call assert_equal('abcd', str[:n])
3747  call assert_equal('d', str[n:n])
3748  unlet n
3749  let nn = 3
3750  call assert_equal('def', str[nn:])
3751  call assert_equal('abcd', str[:nn])
3752  call assert_equal('d', str[nn:nn])
3753  unlet nn
3754  let b:nn = 4
3755  call assert_equal('ef', str[b:nn:])
3756  call assert_equal('abcde', str[:b:nn])
3757  call assert_equal('e', str[b:nn:b:nn])
3758  unlet b:nn
3759endfunc
3760
3761" Test using s: with a typed command              {{{1
3762func Test_typed_script_var()
3763  CheckRunVimInTerminal
3764
3765  let buf = RunVimInTerminal('', {'rows': 6})
3766
3767  " Deep nesting of if ... endif
3768  call term_sendkeys(buf, ":echo get(s:, 'foo', 'x')\n")
3769  call TermWait(buf)
3770  call WaitForAssert({-> assert_match('^E116:', term_getline(buf, 5))})
3771
3772  call StopVimInTerminal(buf)
3773endfunc
3774
3775"-------------------------------------------------------------------------------
3776" Modelines								    {{{1
3777" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
3778"-------------------------------------------------------------------------------
3779