closure.lua 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. -- $Id: closure.lua,v 1.59 2016/11/07 13:11:28 roberto Exp $
  2. -- See Copyright Notice in file all.lua
  3. print "testing closures"
  4. local A,B = 0,{g=10}
  5. function f(x)
  6. local a = {}
  7. for i=1,1000 do
  8. local y = 0
  9. do
  10. a[i] = function () B.g = B.g+1; y = y+x; return y+A end
  11. end
  12. end
  13. local dummy = function () return a[A] end
  14. collectgarbage()
  15. A = 1; assert(dummy() == a[1]); A = 0;
  16. assert(a[1]() == x)
  17. assert(a[3]() == x)
  18. collectgarbage()
  19. assert(B.g == 12)
  20. return a
  21. end
  22. local a = f(10)
  23. -- force a GC in this level
  24. local x = {[1] = {}} -- to detect a GC
  25. setmetatable(x, {__mode = 'kv'})
  26. while x[1] do -- repeat until GC
  27. local a = A..A..A..A -- create garbage
  28. A = A+1
  29. end
  30. assert(a[1]() == 20+A)
  31. assert(a[1]() == 30+A)
  32. assert(a[2]() == 10+A)
  33. collectgarbage()
  34. assert(a[2]() == 20+A)
  35. assert(a[2]() == 30+A)
  36. assert(a[3]() == 20+A)
  37. assert(a[8]() == 10+A)
  38. assert(getmetatable(x).__mode == 'kv')
  39. assert(B.g == 19)
  40. -- testing equality
  41. a = {}
  42. for i = 1, 5 do a[i] = function (x) return x + a + _ENV end end
  43. assert(a[3] == a[4] and a[4] == a[5])
  44. for i = 1, 5 do a[i] = function (x) return i + a + _ENV end end
  45. assert(a[3] ~= a[4] and a[4] ~= a[5])
  46. local function f()
  47. return function (x) return math.sin(_ENV[x]) end
  48. end
  49. assert(f() == f())
  50. -- testing closures with 'for' control variable
  51. a = {}
  52. for i=1,10 do
  53. a[i] = {set = function(x) i=x end, get = function () return i end}
  54. if i == 3 then break end
  55. end
  56. assert(a[4] == nil)
  57. a[1].set(10)
  58. assert(a[2].get() == 2)
  59. a[2].set('a')
  60. assert(a[3].get() == 3)
  61. assert(a[2].get() == 'a')
  62. a = {}
  63. local t = {"a", "b"}
  64. for i = 1, #t do
  65. local k = t[i]
  66. a[i] = {set = function(x, y) i=x; k=y end,
  67. get = function () return i, k end}
  68. if i == 2 then break end
  69. end
  70. a[1].set(10, 20)
  71. local r,s = a[2].get()
  72. assert(r == 2 and s == 'b')
  73. r,s = a[1].get()
  74. assert(r == 10 and s == 20)
  75. a[2].set('a', 'b')
  76. r,s = a[2].get()
  77. assert(r == "a" and s == "b")
  78. -- testing closures with 'for' control variable x break
  79. for i=1,3 do
  80. f = function () return i end
  81. break
  82. end
  83. assert(f() == 1)
  84. for k = 1, #t do
  85. local v = t[k]
  86. f = function () return k, v end
  87. break
  88. end
  89. assert(({f()})[1] == 1)
  90. assert(({f()})[2] == "a")
  91. -- testing closure x break x return x errors
  92. local b
  93. function f(x)
  94. local first = 1
  95. while 1 do
  96. if x == 3 and not first then return end
  97. local a = 'xuxu'
  98. b = function (op, y)
  99. if op == 'set' then
  100. a = x+y
  101. else
  102. return a
  103. end
  104. end
  105. if x == 1 then do break end
  106. elseif x == 2 then return
  107. else if x ~= 3 then error() end
  108. end
  109. first = nil
  110. end
  111. end
  112. for i=1,3 do
  113. f(i)
  114. assert(b('get') == 'xuxu')
  115. b('set', 10); assert(b('get') == 10+i)
  116. b = nil
  117. end
  118. pcall(f, 4);
  119. assert(b('get') == 'xuxu')
  120. b('set', 10); assert(b('get') == 14)
  121. local w
  122. -- testing multi-level closure
  123. function f(x)
  124. return function (y)
  125. return function (z) return w+x+y+z end
  126. end
  127. end
  128. y = f(10)
  129. w = 1.345
  130. assert(y(20)(30) == 60+w)
  131. -- testing closures x repeat-until
  132. local a = {}
  133. local i = 1
  134. repeat
  135. local x = i
  136. a[i] = function () i = x+1; return x end
  137. until i > 10 or a[i]() ~= x
  138. assert(i == 11 and a[1]() == 1 and a[3]() == 3 and i == 4)
  139. -- testing closures created in 'then' and 'else' parts of 'if's
  140. a = {}
  141. for i = 1, 10 do
  142. if i % 3 == 0 then
  143. local y = 0
  144. a[i] = function (x) local t = y; y = x; return t end
  145. elseif i % 3 == 1 then
  146. goto L1
  147. error'not here'
  148. ::L1::
  149. local y = 1
  150. a[i] = function (x) local t = y; y = x; return t end
  151. elseif i % 3 == 2 then
  152. local t
  153. goto l4
  154. ::l4a:: a[i] = t; goto l4b
  155. error("should never be here!")
  156. ::l4::
  157. local y = 2
  158. t = function (x) local t = y; y = x; return t end
  159. goto l4a
  160. error("should never be here!")
  161. ::l4b::
  162. end
  163. end
  164. for i = 1, 10 do
  165. assert(a[i](i * 10) == i % 3 and a[i]() == i * 10)
  166. end
  167. print'+'
  168. -- test for correctly closing upvalues in tail calls of vararg functions
  169. local function t ()
  170. local function c(a,b) assert(a=="test" and b=="OK") end
  171. local function v(f, ...) c("test", f() ~= 1 and "FAILED" or "OK") end
  172. local x = 1
  173. return v(function() return x end)
  174. end
  175. t()
  176. -- test for debug manipulation of upvalues
  177. local debug = require'debug'
  178. do
  179. local a , b, c = 3, 5, 7
  180. foo1 = function () return a+b end;
  181. foo2 = function () return b+a end;
  182. do
  183. local a = 10
  184. foo3 = function () return a+b end;
  185. end
  186. end
  187. assert(debug.upvalueid(foo1, 1))
  188. assert(debug.upvalueid(foo1, 2))
  189. assert(not pcall(debug.upvalueid, foo1, 3))
  190. assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2))
  191. assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1))
  192. assert(debug.upvalueid(foo3, 1))
  193. assert(debug.upvalueid(foo1, 1) ~= debug.upvalueid(foo3, 1))
  194. assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo3, 2))
  195. assert(debug.upvalueid(string.gmatch("x", "x"), 1) ~= nil)
  196. assert(foo1() == 3 + 5 and foo2() == 5 + 3)
  197. debug.upvaluejoin(foo1, 2, foo2, 2)
  198. assert(foo1() == 3 + 3 and foo2() == 5 + 3)
  199. assert(foo3() == 10 + 5)
  200. debug.upvaluejoin(foo3, 2, foo2, 1)
  201. assert(foo3() == 10 + 5)
  202. debug.upvaluejoin(foo3, 2, foo2, 2)
  203. assert(foo3() == 10 + 3)
  204. assert(not pcall(debug.upvaluejoin, foo1, 3, foo2, 1))
  205. assert(not pcall(debug.upvaluejoin, foo1, 1, foo2, 3))
  206. assert(not pcall(debug.upvaluejoin, foo1, 0, foo2, 1))
  207. assert(not pcall(debug.upvaluejoin, print, 1, foo2, 1))
  208. assert(not pcall(debug.upvaluejoin, {}, 1, foo2, 1))
  209. assert(not pcall(debug.upvaluejoin, foo1, 1, print, 1))
  210. print'OK'