1" Test various aspects of the Vim9 script language. 2 3source check.vim 4source view_util.vim 5source vim9.vim 6 7func Test_def_basic() 8 def SomeFunc(): string 9 return 'yes' 10 enddef 11 call assert_equal('yes', SomeFunc()) 12endfunc 13 14def ReturnString(): string 15 return 'string' 16enddef 17 18def ReturnNumber(): number 19 return 123 20enddef 21 22let g:notNumber = 'string' 23 24def ReturnGlobal(): number 25 return g:notNumber 26enddef 27 28def Test_return_something() 29 assert_equal('string', ReturnString()) 30 assert_equal(123, ReturnNumber()) 31 assert_fails('call ReturnGlobal()', 'E1029: Expected number but got string') 32enddef 33 34let s:nothing = 0 35def ReturnNothing() 36 s:nothing = 1 37 if true 38 return 39 endif 40 s:nothing = 2 41enddef 42 43def Test_return_nothing() 44 ReturnNothing() 45 assert_equal(1, s:nothing) 46enddef 47 48func Increment() 49 let g:counter += 1 50endfunc 51 52def Test_call_ufunc_count() 53 g:counter = 1 54 Increment() 55 Increment() 56 Increment() 57 " works with and without :call 58 assert_equal(4, g:counter) 59 call assert_equal(4, g:counter) 60 unlet g:counter 61enddef 62 63def MyVarargs(arg: string, ...rest: list<string>): string 64 let res = arg 65 for s in rest 66 res ..= ',' .. s 67 endfor 68 return res 69enddef 70 71def Test_call_varargs() 72 assert_equal('one', MyVarargs('one')) 73 assert_equal('one,two', MyVarargs('one', 'two')) 74 assert_equal('one,two,three', MyVarargs('one', 'two', 'three')) 75enddef 76 77def MyDefaultArgs(name = 'string'): string 78 return name 79enddef 80 81def Test_call_default_args() 82 assert_equal('string', MyDefaultArgs()) 83 assert_equal('one', MyDefaultArgs('one')) 84 assert_fails('call MyDefaultArgs("one", "two")', 'E118:') 85 86 CheckScriptFailure(['def Func(arg: number = asdf)', 'enddef', 'defcompile'], 'E1001:') 87 CheckScriptFailure(['def Func(arg: number = "text")', 'enddef', 'defcompile'], 'E1013: argument 1: type mismatch, expected number but got string') 88enddef 89 90def Test_nested_function() 91 def Nested(arg: string): string 92 return 'nested ' .. arg 93 enddef 94 assert_equal('nested function', Nested('function')) 95 96 CheckDefFailure(['def Nested()', 'enddef', 'Nested(66)'], 'E118:') 97 CheckDefFailure(['def Nested(arg: string)', 'enddef', 'Nested()'], 'E119:') 98 99 CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:') 100enddef 101 102func Test_call_default_args_from_func() 103 call assert_equal('string', MyDefaultArgs()) 104 call assert_equal('one', MyDefaultArgs('one')) 105 call assert_fails('call MyDefaultArgs("one", "two")', 'E118:') 106endfunc 107 108func TakesOneArg(arg) 109 echo a:arg 110endfunc 111 112def Test_call_wrong_args() 113 call CheckDefFailure(['TakesOneArg()'], 'E119:') 114 call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:') 115 call CheckDefFailure(['bufnr(xxx)'], 'E1001:') 116 call CheckScriptFailure(['def Func(Ref: func(s: string))'], 'E475:') 117enddef 118 119" Default arg and varargs 120def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string 121 let res = one .. ',' .. two 122 for s in rest 123 res ..= ',' .. s 124 endfor 125 return res 126enddef 127 128def Test_call_def_varargs() 129 call assert_fails('call MyDefVarargs()', 'E119:') 130 assert_equal('one,foo', MyDefVarargs('one')) 131 assert_equal('one,two', MyDefVarargs('one', 'two')) 132 assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three')) 133 call CheckDefFailure(['MyDefVarargs("one", 22)'], 'E1013: argument 2: type mismatch, expected string but got number') 134enddef 135 136let s:value = '' 137 138def FuncOneDefArg(opt = 'text') 139 s:value = opt 140enddef 141 142def FuncTwoDefArg(nr = 123, opt = 'text'): string 143 return nr .. opt 144enddef 145 146def FuncVarargs(...arg: list<string>): string 147 return join(arg, ',') 148enddef 149 150def Test_func_type_varargs() 151 let RefDefArg: func(?string) 152 RefDefArg = FuncOneDefArg 153 RefDefArg() 154 assert_equal('text', s:value) 155 RefDefArg('some') 156 assert_equal('some', s:value) 157 158 let RefDef2Arg: func(?number, ?string): string 159 RefDef2Arg = FuncTwoDefArg 160 assert_equal('123text', RefDef2Arg()) 161 assert_equal('99text', RefDef2Arg(99)) 162 assert_equal('77some', RefDef2Arg(77, 'some')) 163 164 call CheckDefFailure(['let RefWrong: func(string?)'], 'E1010:') 165 call CheckDefFailure(['let RefWrong: func(?string, string)'], 'E1007:') 166 167 let RefVarargs: func(...list<string>): string 168 RefVarargs = FuncVarargs 169 assert_equal('', RefVarargs()) 170 assert_equal('one', RefVarargs('one')) 171 assert_equal('one,two', RefVarargs('one', 'two')) 172 173 call CheckDefFailure(['let RefWrong: func(...list<string>, string)'], 'E110:') 174 call CheckDefFailure(['let RefWrong: func(...list<string>, ?string)'], 'E110:') 175enddef 176 177" Only varargs 178def MyVarargsOnly(...args: list<string>): string 179 return join(args, ',') 180enddef 181 182def Test_call_varargs_only() 183 assert_equal('', MyVarargsOnly()) 184 assert_equal('one', MyVarargsOnly('one')) 185 assert_equal('one,two', MyVarargsOnly('one', 'two')) 186 call CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: argument 1: type mismatch, expected string but got number') 187 call CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: argument 2: type mismatch, expected string but got number') 188enddef 189 190def Test_using_var_as_arg() 191 call writefile(['def Func(x: number)', 'let x = 234', 'enddef', 'defcompile'], 'Xdef') 192 call assert_fails('so Xdef', 'E1006:') 193 call delete('Xdef') 194enddef 195 196def DictArg(arg: dict<string>) 197 arg['key'] = 'value' 198enddef 199 200def ListArg(arg: list<string>) 201 arg[0] = 'value' 202enddef 203 204def Test_assign_to_argument() 205 " works for dict and list 206 let d: dict<string> = {} 207 DictArg(d) 208 assert_equal('value', d['key']) 209 let l: list<string> = [] 210 ListArg(l) 211 assert_equal('value', l[0]) 212 213 call CheckScriptFailure(['def Func(arg: number)', 'arg = 3', 'enddef', 'defcompile'], 'E1090:') 214enddef 215 216def Test_call_func_defined_later() 217 call assert_equal('one', g:DefinedLater('one')) 218 call assert_fails('call NotDefined("one")', 'E117:') 219enddef 220 221func DefinedLater(arg) 222 return a:arg 223endfunc 224 225def Test_call_funcref() 226 assert_equal(3, g:SomeFunc('abc')) 227 assert_fails('NotAFunc()', 'E117:') 228 assert_fails('g:NotAFunc()', 'E117:') 229enddef 230 231let SomeFunc = function('len') 232let NotAFunc = 'text' 233 234def CombineFuncrefTypes() 235 " same arguments, different return type 236 let Ref1: func(bool): string 237 let Ref2: func(bool): number 238 let Ref3: func(bool): any 239 Ref3 = g:cond ? Ref1 : Ref2 240 241 " different number of arguments 242 let Refa1: func(bool): number 243 let Refa2: func(bool, number): number 244 let Refa3: func: number 245 Refa3 = g:cond ? Refa1 : Refa2 246 247 " different argument types 248 let Refb1: func(bool, string): number 249 let Refb2: func(string, number): number 250 let Refb3: func(any, any): number 251 Refb3 = g:cond ? Refb1 : Refb2 252enddef 253 254def FuncWithForwardCall() 255 return g:DefinedEvenLater("yes") 256enddef 257 258def DefinedEvenLater(arg: string): string 259 return arg 260enddef 261 262def Test_error_in_nested_function() 263 " Error in called function requires unwinding the call stack. 264 assert_fails('call FuncWithForwardCall()', 'E1013') 265enddef 266 267def Test_return_type_wrong() 268 CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef', 'defcompile'], 'expected number but got string') 269 CheckScriptFailure(['def Func(): string', 'return 1', 'enddef', 'defcompile'], 'expected string but got number') 270 CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef', 'defcompile'], 'expected void but got string') 271 CheckScriptFailure(['def Func()', 'return "a"', 'enddef', 'defcompile'], 'expected void but got string') 272 273 CheckScriptFailure(['def Func(): number', 'return', 'enddef', 'defcompile'], 'E1003:') 274 275 CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:') 276 CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:') 277 CheckScriptFailure(['def Func()', 'return 1'], 'E1057:') 278enddef 279 280def Test_arg_type_wrong() 281 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>') 282 CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...') 283 CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:') 284 CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:') 285enddef 286 287def Test_vim9script_call() 288 let lines =<< trim END 289 vim9script 290 let var = '' 291 def MyFunc(arg: string) 292 var = arg 293 enddef 294 MyFunc('foobar') 295 assert_equal('foobar', var) 296 297 let str = 'barfoo' 298 str->MyFunc() 299 assert_equal('barfoo', var) 300 301 let g:value = 'value' 302 g:value->MyFunc() 303 assert_equal('value', var) 304 305 let listvar = [] 306 def ListFunc(arg: list<number>) 307 listvar = arg 308 enddef 309 [1, 2, 3]->ListFunc() 310 assert_equal([1, 2, 3], listvar) 311 312 let dictvar = {} 313 def DictFunc(arg: dict<number>) 314 dictvar = arg 315 enddef 316 {'a': 1, 'b': 2}->DictFunc() 317 assert_equal(#{a: 1, b: 2}, dictvar) 318 def CompiledDict() 319 {'a': 3, 'b': 4}->DictFunc() 320 enddef 321 CompiledDict() 322 assert_equal(#{a: 3, b: 4}, dictvar) 323 324 #{a: 3, b: 4}->DictFunc() 325 assert_equal(#{a: 3, b: 4}, dictvar) 326 327 ('text')->MyFunc() 328 assert_equal('text', var) 329 ("some")->MyFunc() 330 assert_equal('some', var) 331 END 332 writefile(lines, 'Xcall.vim') 333 source Xcall.vim 334 delete('Xcall.vim') 335enddef 336 337def Test_vim9script_call_fail_decl() 338 let lines =<< trim END 339 vim9script 340 let var = '' 341 def MyFunc(arg: string) 342 let var = 123 343 enddef 344 defcompile 345 END 346 writefile(lines, 'Xcall_decl.vim') 347 assert_fails('source Xcall_decl.vim', 'E1054:') 348 delete('Xcall_decl.vim') 349enddef 350 351def Test_vim9script_call_fail_const() 352 let lines =<< trim END 353 vim9script 354 const var = '' 355 def MyFunc(arg: string) 356 var = 'asdf' 357 enddef 358 defcompile 359 END 360 writefile(lines, 'Xcall_const.vim') 361 assert_fails('source Xcall_const.vim', 'E46:') 362 delete('Xcall_const.vim') 363enddef 364 365" Test that inside :function a Python function can be defined, :def is not 366" recognized. 367func Test_function_python() 368 CheckFeature python3 369 let py = 'python3' 370 execute py "<< EOF" 371def do_something(): 372 return 1 373EOF 374endfunc 375 376def Test_delfunc() 377 let lines =<< trim END 378 vim9script 379 def g:GoneSoon() 380 echo 'hello' 381 enddef 382 383 def CallGoneSoon() 384 GoneSoon() 385 enddef 386 defcompile 387 388 delfunc g:GoneSoon 389 CallGoneSoon() 390 END 391 writefile(lines, 'XToDelFunc') 392 assert_fails('so XToDelFunc', 'E933') 393 assert_fails('so XToDelFunc', 'E933') 394 395 delete('XToDelFunc') 396enddef 397 398def Test_redef_failure() 399 call writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef') 400 so Xdef 401 call writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef') 402 so Xdef 403 call writefile(['def! Func0(): string', 'enddef', 'defcompile'], 'Xdef') 404 call assert_fails('so Xdef', 'E1027:') 405 call writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef') 406 so Xdef 407 call delete('Xdef') 408 409 call assert_equal(0, g:Func0()) 410 call assert_equal('Func1', g:Func1()) 411 call assert_equal('Func2', g:Func2()) 412 413 delfunc! Func0 414 delfunc! Func1 415 delfunc! Func2 416enddef 417 418def Test_vim9script_func() 419 let lines =<< trim END 420 vim9script 421 func Func(arg) 422 echo a:arg 423 endfunc 424 Func('text') 425 END 426 writefile(lines, 'XVim9Func') 427 so XVim9Func 428 429 delete('XVim9Func') 430enddef 431 432" Test for internal functions returning different types 433func Test_InternalFuncRetType() 434 let lines =<< trim END 435 def RetFloat(): float 436 return ceil(1.456) 437 enddef 438 439 def RetListAny(): list<any> 440 return items({'k' : 'v'}) 441 enddef 442 443 def RetListString(): list<string> 444 return split('a:b:c', ':') 445 enddef 446 447 def RetListDictAny(): list<dict<any>> 448 return getbufinfo() 449 enddef 450 451 def RetDictNumber(): dict<number> 452 return wordcount() 453 enddef 454 455 def RetDictString(): dict<string> 456 return environ() 457 enddef 458 END 459 call writefile(lines, 'Xscript') 460 source Xscript 461 462 call assert_equal(2.0, RetFloat()) 463 call assert_equal([['k', 'v']], RetListAny()) 464 call assert_equal(['a', 'b', 'c'], RetListString()) 465 call assert_notequal([], RetListDictAny()) 466 call assert_notequal({}, RetDictNumber()) 467 call assert_notequal({}, RetDictString()) 468 call delete('Xscript') 469endfunc 470 471" Test for passing too many or too few arguments to internal functions 472func Test_internalfunc_arg_error() 473 let l =<< trim END 474 def! FArgErr(): float 475 return ceil(1.1, 2) 476 enddef 477 defcompile 478 END 479 call writefile(l, 'Xinvalidarg') 480 call assert_fails('so Xinvalidarg', 'E118:') 481 let l =<< trim END 482 def! FArgErr(): float 483 return ceil() 484 enddef 485 defcompile 486 END 487 call writefile(l, 'Xinvalidarg') 488 call assert_fails('so Xinvalidarg', 'E119:') 489 call delete('Xinvalidarg') 490endfunc 491 492let s:funcResult = 0 493 494def FuncNoArgNoRet() 495 funcResult = 11 496enddef 497 498def FuncNoArgRetNumber(): number 499 funcResult = 22 500 return 1234 501enddef 502 503def FuncNoArgRetString(): string 504 funcResult = 45 505 return 'text' 506enddef 507 508def FuncOneArgNoRet(arg: number) 509 funcResult = arg 510enddef 511 512def FuncOneArgRetNumber(arg: number): number 513 funcResult = arg 514 return arg 515enddef 516 517def FuncTwoArgNoRet(one: bool, two: number) 518 funcResult = two 519enddef 520 521def FuncOneArgRetString(arg: string): string 522 return arg 523enddef 524 525def FuncOneArgRetAny(arg: any): any 526 return arg 527enddef 528 529def Test_func_type() 530 let Ref1: func() 531 funcResult = 0 532 Ref1 = FuncNoArgNoRet 533 Ref1() 534 assert_equal(11, funcResult) 535 536 let Ref2: func 537 funcResult = 0 538 Ref2 = FuncNoArgNoRet 539 Ref2() 540 assert_equal(11, funcResult) 541 542 funcResult = 0 543 Ref2 = FuncOneArgNoRet 544 Ref2(12) 545 assert_equal(12, funcResult) 546 547 funcResult = 0 548 Ref2 = FuncNoArgRetNumber 549 assert_equal(1234, Ref2()) 550 assert_equal(22, funcResult) 551 552 funcResult = 0 553 Ref2 = FuncOneArgRetNumber 554 assert_equal(13, Ref2(13)) 555 assert_equal(13, funcResult) 556enddef 557 558def Test_func_type_part() 559 let RefVoid: func: void 560 RefVoid = FuncNoArgNoRet 561 RefVoid = FuncOneArgNoRet 562 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') 563 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string') 564 565 let RefAny: func(): any 566 RefAny = FuncNoArgRetNumber 567 RefAny = FuncNoArgRetString 568 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()') 569 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)') 570 571 let RefNr: func: number 572 RefNr = FuncNoArgRetNumber 573 RefNr = FuncOneArgRetNumber 574 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()') 575 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string') 576 577 let RefStr: func: string 578 RefStr = FuncNoArgRetString 579 RefStr = FuncOneArgRetString 580 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()') 581 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number') 582enddef 583 584def Test_func_type_fails() 585 CheckDefFailure(['let ref1: func()'], 'E704:') 586 587 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') 588 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: type mismatch, expected func() but got func(number)') 589 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: type mismatch, expected func() but got func(number): number') 590 CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(bool) but got func(bool, number)') 591 CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(?bool) but got func(bool, number)') 592 CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(...bool) but got func(bool, number)') 593 594 call CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:') 595 call CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:') 596 call CheckDefFailure(['let RefWrong: func(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)'], 'E740:') 597 call CheckDefFailure(['let RefWrong: func(bool):string'], 'E1069:') 598enddef 599 600def Test_func_return_type() 601 let nr: number 602 nr = FuncNoArgRetNumber() 603 assert_equal(1234, nr) 604 605 nr = FuncOneArgRetAny(122) 606 assert_equal(122, nr) 607 608 let str: string 609 str = FuncOneArgRetAny('yes') 610 assert_equal('yes', str) 611 612 CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1013: type mismatch, expected string but got number') 613enddef 614 615def MultiLine( 616 arg1: string, 617 arg2 = 1234, 618 ...rest: list<string> 619 ): string 620 return arg1 .. arg2 .. join(rest, '-') 621enddef 622 623def MultiLineComment( 624 arg1: string, # comment 625 arg2 = 1234, # comment 626 ...rest: list<string> # comment 627 ): string # comment 628 return arg1 .. arg2 .. join(rest, '-') 629enddef 630 631def Test_multiline() 632 assert_equal('text1234', MultiLine('text')) 633 assert_equal('text777', MultiLine('text', 777)) 634 assert_equal('text777one', MultiLine('text', 777, 'one')) 635 assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two')) 636enddef 637 638func Test_multiline_not_vim9() 639 call assert_equal('text1234', MultiLine('text')) 640 call assert_equal('text777', MultiLine('text', 777)) 641 call assert_equal('text777one', MultiLine('text', 777, 'one')) 642 call assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two')) 643endfunc 644 645 646" When using CheckScriptFailure() for the below test, E1010 is generated instead 647" of E1056. 648func Test_E1056_1059() 649 let caught_1056 = 0 650 try 651 def F(): 652 return 1 653 enddef 654 catch /E1056:/ 655 let caught_1056 = 1 656 endtry 657 call assert_equal(1, caught_1056) 658 659 let caught_1059 = 0 660 try 661 def F5(items : list) 662 echo 'a' 663 enddef 664 catch /E1059:/ 665 let caught_1059 = 1 666 endtry 667 call assert_equal(1, caught_1059) 668endfunc 669 670func DelMe() 671 echo 'DelMe' 672endfunc 673 674def Test_deleted_function() 675 CheckDefExecFailure([ 676 'let RefMe: func = function("g:DelMe")', 677 'delfunc g:DelMe', 678 'echo RefMe()'], 'E117:') 679enddef 680 681def Test_unknown_function() 682 CheckDefExecFailure([ 683 'let Ref: func = function("NotExist")', 684 'delfunc g:NotExist'], 'E130:') 685enddef 686 687def RefFunc(Ref: func(string): string): string 688 return Ref('more') 689enddef 690 691def Test_closure_simple() 692 let local = 'some ' 693 assert_equal('some more', RefFunc({s -> local .. s})) 694enddef 695 696def MakeRef() 697 let local = 'some ' 698 g:Ref = {s -> local .. s} 699enddef 700 701def Test_closure_ref_after_return() 702 MakeRef() 703 assert_equal('some thing', g:Ref('thing')) 704 unlet g:Ref 705enddef 706 707def MakeTwoRefs() 708 let local = ['some'] 709 g:Extend = {s -> local->add(s)} 710 g:Read = {-> local} 711enddef 712 713def Test_closure_two_refs() 714 MakeTwoRefs() 715 assert_equal('some', join(g:Read(), ' ')) 716 g:Extend('more') 717 assert_equal('some more', join(g:Read(), ' ')) 718 g:Extend('even') 719 assert_equal('some more even', join(g:Read(), ' ')) 720 721 unlet g:Extend 722 unlet g:Read 723enddef 724 725def ReadRef(Ref: func(): list<string>): string 726 return join(Ref(), ' ') 727enddef 728 729def ExtendRef(Ref: func(string), add: string) 730 Ref(add) 731enddef 732 733def Test_closure_two_indirect_refs() 734 MakeTwoRefs() 735 assert_equal('some', ReadRef(g:Read)) 736 ExtendRef(g:Extend, 'more') 737 assert_equal('some more', ReadRef(g:Read)) 738 ExtendRef(g:Extend, 'even') 739 assert_equal('some more even', ReadRef(g:Read)) 740 741 unlet g:Extend 742 unlet g:Read 743enddef 744 745def MakeArgRefs(theArg: string) 746 let local = 'loc_val' 747 g:UseArg = {s -> theArg .. '/' .. local .. '/' .. s} 748enddef 749 750def MakeArgRefsVarargs(theArg: string, ...rest: list<string>) 751 let local = 'the_loc' 752 g:UseVararg = {s -> theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest)} 753enddef 754 755def Test_closure_using_argument() 756 MakeArgRefs('arg_val') 757 assert_equal('arg_val/loc_val/call_val', g:UseArg('call_val')) 758 759 MakeArgRefsVarargs('arg_val', 'one', 'two') 760 assert_equal('arg_val/the_loc/call_val/one two', g:UseVararg('call_val')) 761 762 unlet g:UseArg 763 unlet g:UseVararg 764enddef 765 766def MakeGetAndAppendRefs() 767 let local = 'a' 768 769 def Append(arg: string) 770 local ..= arg 771 enddef 772 g:Append = Append 773 774 def Get(): string 775 return local 776 enddef 777 g:Get = Get 778enddef 779 780def Test_closure_append_get() 781 MakeGetAndAppendRefs() 782 assert_equal('a', g:Get()) 783 g:Append('-b') 784 assert_equal('a-b', g:Get()) 785 g:Append('-c') 786 assert_equal('a-b-c', g:Get()) 787 788 unlet g:Append 789 unlet g:Get 790enddef 791 792def Test_nested_closure() 793 let local = 'text' 794 def Closure(arg: string): string 795 return local .. arg 796 enddef 797 assert_equal('text!!!', Closure('!!!')) 798enddef 799 800func GetResult(Ref) 801 return a:Ref('some') 802endfunc 803 804def Test_call_closure_not_compiled() 805 let text = 'text' 806 g:Ref = {s -> s .. text} 807 assert_equal('sometext', GetResult(g:Ref)) 808enddef 809 810 811" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 812