test_lambda.vim 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. " Test for lambda and closure
  2. func Test_lambda_feature()
  3. call assert_equal(1, has('lambda'))
  4. endfunc
  5. func Test_lambda_with_filter()
  6. let s:x = 2
  7. call assert_equal([2, 3], filter([1, 2, 3], {i, v -> v >= s:x}))
  8. endfunc
  9. func Test_lambda_with_map()
  10. let s:x = 1
  11. call assert_equal([2, 3, 4], map([1, 2, 3], {i, v -> v + s:x}))
  12. endfunc
  13. func Test_lambda_with_sort()
  14. call assert_equal([1, 2, 3, 4, 7], sort([3,7,2,1,4], {a, b -> a - b}))
  15. endfunc
  16. func Test_lambda_with_timer()
  17. if !has('timers')
  18. return
  19. endif
  20. let s:n = 0
  21. let s:timer_id = 0
  22. func! s:Foo()
  23. let s:timer_id = timer_start(10, {-> execute("let s:n += 1 | echo s:n", "")}, {"repeat": -1})
  24. endfunc
  25. call s:Foo()
  26. " check timer works
  27. for i in range(0, 10)
  28. if s:n > 0
  29. break
  30. endif
  31. sleep 10m
  32. endfor
  33. " do not collect lambda
  34. call test_garbagecollect_now()
  35. " check timer still works
  36. let m = s:n
  37. for i in range(0, 10)
  38. if s:n > m
  39. break
  40. endif
  41. sleep 10m
  42. endfor
  43. call timer_stop(s:timer_id)
  44. call assert_true(s:n > m)
  45. endfunc
  46. func Test_lambda_with_partial()
  47. let l:Cb = function({... -> ['zero', a:1, a:2, a:3]}, ['one', 'two'])
  48. call assert_equal(['zero', 'one', 'two', 'three'], l:Cb('three'))
  49. endfunc
  50. function Test_lambda_fails()
  51. call assert_equal(3, {a, b -> a + b}(1, 2))
  52. call assert_fails('echo {a, a -> a + a}(1, 2)', 'E853:')
  53. call assert_fails('echo {a, b -> a + b)}(1, 2)', 'E451:')
  54. echo assert_fails('echo 10->{a -> a + 2}', 'E107:')
  55. endfunc
  56. func Test_not_lambda()
  57. let x = {'>' : 'foo'}
  58. call assert_equal('foo', x['>'])
  59. endfunc
  60. func Test_lambda_capture_by_reference()
  61. let v = 1
  62. let l:F = {x -> x + v}
  63. let v = 2
  64. call assert_equal(12, l:F(10))
  65. endfunc
  66. func Test_lambda_side_effect()
  67. func! s:update_and_return(arr)
  68. let a:arr[1] = 5
  69. return a:arr
  70. endfunc
  71. func! s:foo(arr)
  72. return {-> s:update_and_return(a:arr)}
  73. endfunc
  74. let arr = [3,2,1]
  75. call assert_equal([3, 5, 1], s:foo(arr)())
  76. endfunc
  77. func Test_lambda_refer_local_variable_from_other_scope()
  78. func! s:foo(X)
  79. return a:X() " refer l:x in s:bar()
  80. endfunc
  81. func! s:bar()
  82. let x = 123
  83. return s:foo({-> x})
  84. endfunc
  85. call assert_equal(123, s:bar())
  86. endfunc
  87. func Test_lambda_do_not_share_local_variable()
  88. func! s:define_funcs()
  89. let l:One = {-> split(execute("let a = 'abc' | echo a"))[0]}
  90. let l:Two = {-> exists("a") ? a : "no"}
  91. return [l:One, l:Two]
  92. endfunc
  93. let l:F = s:define_funcs()
  94. call assert_equal('no', l:F[1]())
  95. call assert_equal('abc', l:F[0]())
  96. call assert_equal('no', l:F[1]())
  97. endfunc
  98. func Test_lambda_closure_counter()
  99. func! s:foo()
  100. let x = 0
  101. return {-> [execute("let x += 1"), x][-1]}
  102. endfunc
  103. let l:F = s:foo()
  104. call test_garbagecollect_now()
  105. call assert_equal(1, l:F())
  106. call assert_equal(2, l:F())
  107. call assert_equal(3, l:F())
  108. call assert_equal(4, l:F())
  109. endfunc
  110. func Test_lambda_with_a_var()
  111. func! s:foo()
  112. let x = 2
  113. return {... -> a:000 + [x]}
  114. endfunc
  115. func! s:bar()
  116. return s:foo()(1)
  117. endfunc
  118. call assert_equal([1, 2], s:bar())
  119. endfunc
  120. func Test_lambda_call_lambda_from_lambda()
  121. func! s:foo(x)
  122. let l:F1 = {-> {-> a:x}}
  123. return {-> l:F1()}
  124. endfunc
  125. let l:F = s:foo(1)
  126. call assert_equal(1, l:F()())
  127. endfunc
  128. func Test_lambda_delfunc()
  129. func! s:gen()
  130. let pl = l:
  131. let l:Foo = {-> get(pl, "Foo", get(pl, "Bar", {-> 0}))}
  132. let l:Bar = l:Foo
  133. delfunction l:Foo
  134. return l:Bar
  135. endfunc
  136. let l:F = s:gen()
  137. call assert_fails(':call l:F()', 'E933:')
  138. endfunc
  139. func Test_lambda_scope()
  140. func! s:NewCounter()
  141. let c = 0
  142. return {-> [execute('let c += 1'), c][-1]}
  143. endfunc
  144. func! s:NewCounter2()
  145. return {-> [execute('let c += 100'), c][-1]}
  146. endfunc
  147. let l:C = s:NewCounter()
  148. let l:D = s:NewCounter2()
  149. call assert_equal(1, l:C())
  150. call assert_fails(':call l:D()', 'E121:')
  151. call assert_equal(2, l:C())
  152. endfunc
  153. func Test_lambda_share_scope()
  154. func! s:New()
  155. let c = 0
  156. let l:Inc0 = {-> [execute('let c += 1'), c][-1]}
  157. let l:Dec0 = {-> [execute('let c -= 1'), c][-1]}
  158. return [l:Inc0, l:Dec0]
  159. endfunc
  160. let [l:Inc, l:Dec] = s:New()
  161. call assert_equal(1, l:Inc())
  162. call assert_equal(2, l:Inc())
  163. call assert_equal(1, l:Dec())
  164. endfunc
  165. func Test_lambda_circular_reference()
  166. func! s:Foo()
  167. let d = {}
  168. let d.f = {-> d}
  169. return d.f
  170. endfunc
  171. call s:Foo()
  172. call test_garbagecollect_now()
  173. let i = 0 | while i < 10000 | call s:Foo() | let i+= 1 | endwhile
  174. call test_garbagecollect_now()
  175. endfunc
  176. func Test_lambda_combination()
  177. call assert_equal(2, {x -> {x -> x}}(1)(2))
  178. call assert_equal(10, {y -> {x -> x(y)(10)}({y -> y})}({z -> z}))
  179. if has('float')
  180. call assert_equal(5.0, {x -> {y -> x / y}}(10)(2.0))
  181. endif
  182. call assert_equal(6, {x -> {y -> {z -> x + y + z}}}(1)(2)(3))
  183. call assert_equal(6, {x -> {f -> f(x)}}(3)({x -> x * 2}))
  184. call assert_equal(6, {f -> {x -> f(x)}}({x -> x * 2})(3))
  185. " Z combinator
  186. let Z = {f -> {x -> f({y -> x(x)(y)})}({x -> f({y -> x(x)(y)})})}
  187. let Fact = {f -> {x -> x == 0 ? 1 : x * f(x - 1)}}
  188. call assert_equal(120, Z(Fact)(5))
  189. endfunc
  190. func Test_closure_counter()
  191. func! s:foo()
  192. let x = 0
  193. func! s:bar() closure
  194. let x += 1
  195. return x
  196. endfunc
  197. return function('s:bar')
  198. endfunc
  199. let l:F = s:foo()
  200. call test_garbagecollect_now()
  201. call assert_equal(1, l:F())
  202. call assert_equal(2, l:F())
  203. call assert_equal(3, l:F())
  204. call assert_equal(4, l:F())
  205. call assert_match("^\n function <SNR>\\d\\+_bar() closure"
  206. \ .. "\n1 let x += 1"
  207. \ .. "\n2 return x"
  208. \ .. "\n endfunction$", execute('func s:bar'))
  209. endfunc
  210. func Test_closure_unlet()
  211. func! s:foo()
  212. let x = 1
  213. func! s:bar() closure
  214. unlet x
  215. endfunc
  216. call s:bar()
  217. return l:
  218. endfunc
  219. call assert_false(has_key(s:foo(), 'x'))
  220. call test_garbagecollect_now()
  221. endfunc
  222. func LambdaFoo()
  223. let x = 0
  224. func! LambdaBar() closure
  225. let x += 1
  226. return x
  227. endfunc
  228. return function('LambdaBar')
  229. endfunc
  230. func Test_closure_refcount()
  231. let g:Count = LambdaFoo()
  232. call test_garbagecollect_now()
  233. call assert_equal(1, g:Count())
  234. let g:Count2 = LambdaFoo()
  235. call test_garbagecollect_now()
  236. call assert_equal(1, g:Count2())
  237. call assert_equal(2, g:Count())
  238. call assert_equal(3, g:Count2())
  239. delfunc LambdaFoo
  240. delfunc LambdaBar
  241. endfunc
  242. " This test is causing a use-after-free on shutdown.
  243. func Test_named_function_closure()
  244. func! Afoo()
  245. let x = 14
  246. func! s:Abar() closure
  247. return x
  248. endfunc
  249. call assert_equal(14, s:Abar())
  250. endfunc
  251. call Afoo()
  252. call assert_equal(14, s:Abar())
  253. call test_garbagecollect_now()
  254. call assert_equal(14, s:Abar())
  255. endfunc
  256. func Test_lambda_with_index()
  257. let List = {x -> [x]}
  258. let Extract = {-> function(List, ['foobar'])()[0]}
  259. call assert_equal('foobar', Extract())
  260. endfunc
  261. func Test_lambda_error()
  262. " This was causing a crash
  263. call assert_fails('ec{@{->{d->()()', 'E15')
  264. endfunc
  265. func Test_closure_error()
  266. let l =<< trim END
  267. func F1() closure
  268. return 1
  269. endfunc
  270. END
  271. call writefile(l, 'Xscript')
  272. let caught_932 = 0
  273. try
  274. source Xscript
  275. catch /E932:/
  276. let caught_932 = 1
  277. endtry
  278. call assert_equal(1, caught_932)
  279. call delete('Xscript')
  280. endfunc
  281. " vim: shiftwidth=2 sts=2 expandtab