neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

test_vimscript.vim (196950B)


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