closure.lua 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. print("testing closures")
  2. local A, B = 0, { g = 10 }
  3. function f(x)
  4. local a = {}
  5. for i = 1, 1000 do
  6. local y = 0
  7. do
  8. a[i] = function()
  9. B.g = B.g + 1; y = y + x; return y + A
  10. 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] = {
  67. set = function(x, y)
  68. i = x; k = y
  69. end,
  70. get = function() return i, k end
  71. }
  72. if i == 2 then break end
  73. end
  74. a[1].set(10, 20)
  75. local r, s = a[2].get()
  76. assert(r == 2 and s == 'b')
  77. r, s = a[1].get()
  78. assert(r == 10 and s == 20)
  79. a[2].set('a', 'b')
  80. r, s = a[2].get()
  81. assert(r == "a" and s == "b")
  82. -- testing closures with 'for' control variable x break
  83. for i = 1, 3 do
  84. f = function() return i end
  85. break
  86. end
  87. assert(f() == 1)
  88. for k = 1, #t do
  89. local v = t[k]
  90. f = function() return k, v end
  91. break
  92. end
  93. assert(({ f() })[1] == 1)
  94. assert(({ f() })[2] == "a")
  95. -- testing closure x break x return x errors
  96. local b
  97. function f(x)
  98. local first = 1
  99. while 1 do
  100. if x == 3 and not first then return end
  101. local a = 'xuxu'
  102. b = function(op, y)
  103. if op == 'set' then
  104. a = x + y
  105. else
  106. return a
  107. end
  108. end
  109. if x == 1 then
  110. do break end
  111. elseif x == 2 then
  112. return
  113. else
  114. if x ~= 3 then error() end
  115. end
  116. first = nil
  117. end
  118. end
  119. for i = 1, 3 do
  120. f(i)
  121. assert(b('get') == 'xuxu')
  122. b('set', 10); assert(b('get') == 10 + i)
  123. b = nil
  124. end
  125. pcall(f, 4);
  126. assert(b('get') == 'xuxu')
  127. b('set', 10); assert(b('get') == 14)
  128. local w
  129. -- testing multi-level closure
  130. function f(x)
  131. return function(y)
  132. return function(z) return w + x + y + z end
  133. end
  134. end
  135. y = f(10)
  136. w = 1.345
  137. assert(y(20)(30) == 60 + w)
  138. -- testing closures x repeat-until
  139. local a = {}
  140. local i = 1
  141. repeat
  142. local x = i
  143. a[i] = function()
  144. i = x + 1; return x
  145. end
  146. until i > 10 or a[i]() ~= x
  147. assert(i == 11 and a[1]() == 1 and a[3]() == 3 and i == 4)
  148. -- testing closures created in 'then' and 'else' parts of 'if's
  149. a = {}
  150. for i = 1, 10 do
  151. if i % 3 == 0 then
  152. local y = 0
  153. a[i] = function(x)
  154. local t = y; y = x; return t
  155. end
  156. elseif i % 3 == 1 then
  157. goto L1
  158. error 'not here'
  159. ::L1::
  160. local y = 1
  161. a[i] = function(x)
  162. local t = y; y = x; return t
  163. end
  164. elseif i % 3 == 2 then
  165. local t
  166. goto l4
  167. ::l4a::
  168. a[i] = t; goto l4b
  169. error("should never be here!")
  170. ::l4::
  171. local y = 2
  172. t = function(x)
  173. local t = y; y = x; return t
  174. end
  175. goto l4a
  176. error("should never be here!")
  177. ::l4b::
  178. end
  179. end
  180. for i = 1, 10 do
  181. assert(a[i](i * 10) == i % 3 and a[i]() == i * 10)
  182. end
  183. print '+'
  184. -- test for correctly closing upvalues in tail calls of vararg functions
  185. local function t()
  186. local function c(a, b) assert(a == "test" and b == "OK") end
  187. local function v(f, ...) c("test", f() ~= 1 and "FAILED" or "OK") end
  188. local x = 1
  189. return v(function() return x end)
  190. end
  191. t()
  192. -- test for debug manipulation of upvalues
  193. -- local debug = require'debug'
  194. -- do
  195. -- local a , b, c = 3, 5, 7
  196. -- foo1 = function () return a+b end;
  197. -- foo2 = function () return b+a end;
  198. -- do
  199. -- local a = 10
  200. -- foo3 = function () return a+b end;
  201. -- end
  202. -- end
  203. -- assert(debug.upvalueid(foo1, 1))
  204. -- assert(debug.upvalueid(foo1, 2))
  205. -- assert(not pcall(debug.upvalueid, foo1, 3))
  206. -- assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2))
  207. -- assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1))
  208. -- assert(debug.upvalueid(foo3, 1))
  209. -- assert(debug.upvalueid(foo1, 1) ~= debug.upvalueid(foo3, 1))
  210. -- assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo3, 2))
  211. -- assert(debug.upvalueid(string.gmatch("x", "x"), 1) ~= nil)
  212. -- assert(foo1() == 3 + 5 and foo2() == 5 + 3)
  213. -- debug.upvaluejoin(foo1, 2, foo2, 2)
  214. -- assert(foo1() == 3 + 3 and foo2() == 5 + 3)
  215. -- assert(foo3() == 10 + 5)
  216. -- debug.upvaluejoin(foo3, 2, foo2, 1)
  217. -- assert(foo3() == 10 + 5)
  218. -- debug.upvaluejoin(foo3, 2, foo2, 2)
  219. -- assert(foo3() == 10 + 3)
  220. -- assert(not pcall(debug.upvaluejoin, foo1, 3, foo2, 1))
  221. -- assert(not pcall(debug.upvaluejoin, foo1, 1, foo2, 3))
  222. -- assert(not pcall(debug.upvaluejoin, foo1, 0, foo2, 1))
  223. -- assert(not pcall(debug.upvaluejoin, print, 1, foo2, 1))
  224. -- assert(not pcall(debug.upvaluejoin, {}, 1, foo2, 1))
  225. -- assert(not pcall(debug.upvaluejoin, foo1, 1, print, 1))
  226. print('OK')