events.lua 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. print('testing metatables')
  2. X = 20; B = 30
  3. _ENV = setmetatable({}, {__index=_G})
  4. collectgarbage()
  5. X = X+10
  6. assert(X == 30 and _G.X == 20)
  7. B = false
  8. assert(B == false)
  9. B = nil
  10. assert(B == 30)
  11. assert(getmetatable{} == nil)
  12. assert(getmetatable(4) == nil)
  13. assert(getmetatable(nil) == nil)
  14. a={}; setmetatable(a, {__metatable = "xuxu",
  15. __tostring=function(x) return x.name end})
  16. assert(getmetatable(a) == "xuxu")
  17. assert(tostring(a) == nil)
  18. -- cannot change a protected metatable
  19. assert(pcall(setmetatable, a, {}) == false)
  20. a.name = "gororoba"
  21. assert(tostring(a) == "gororoba")
  22. local a, t = {10,20,30; x="10", y="20"}, {}
  23. assert(setmetatable(a,t) == a)
  24. assert(getmetatable(a) == t)
  25. assert(setmetatable(a,nil) == a)
  26. assert(getmetatable(a) == nil)
  27. assert(setmetatable(a,t) == a)
  28. function f (t, i, e)
  29. assert(not e)
  30. local p = rawget(t, "parent")
  31. return (p and p[i]+3), "dummy return"
  32. end
  33. t.__index = f
  34. a.parent = {z=25, x=12, [4] = 24}
  35. assert(a[1] == 10 and a.z == 28 and a[4] == 27 and a.x == "10")
  36. collectgarbage()
  37. a = setmetatable({}, t)
  38. function f(t, i, v) rawset(t, i, v-3) end
  39. setmetatable(t, t) -- causes a bug in 5.1 !
  40. t.__newindex = f
  41. a[1] = 30; a.x = "101"; a[5] = 200
  42. assert(a[1] == 27 and a.x == 98 and a[5] == 197)
  43. local c = {}
  44. a = setmetatable({}, t)
  45. t.__newindex = c
  46. a[1] = 10; a[2] = 20; a[3] = 90
  47. assert(c[1] == 10 and c[2] == 20 and c[3] == 90)
  48. do
  49. local a;
  50. a = setmetatable({}, {__index = setmetatable({},
  51. {__index = setmetatable({},
  52. {__index = function (_,n) return a[n-3]+4, "lixo" end})})})
  53. a[0] = 20
  54. for i=0,10 do
  55. assert(a[i*3] == 20 + i*4)
  56. end
  57. end
  58. do -- newindex
  59. local foi
  60. local a = {}
  61. for i=1,10 do a[i] = 0; a['a'..i] = 0; end
  62. setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end})
  63. foi = false; a[1]=0; assert(not foi)
  64. foi = false; a['a1']=0; assert(not foi)
  65. foi = false; a['a11']=0; assert(foi)
  66. foi = false; a[11]=0; assert(foi)
  67. foi = false; a[1]=nil; assert(not foi)
  68. foi = false; a[1]=nil; assert(foi)
  69. end
  70. setmetatable(t, nil)
  71. function f (t, ...) return t, {...} end
  72. t.__call = f
  73. do
  74. local x,y = a(table.unpack{'a', 1})
  75. assert(x==a and y[1]=='a' and y[2]==1 and y[3]==nil)
  76. x,y = a()
  77. assert(x==a and y[1]==nil)
  78. end
  79. local b = setmetatable({}, t)
  80. setmetatable(b,t)
  81. function f(op)
  82. return function (...) cap = {[0] = op, ...} ; return (...) end
  83. end
  84. t.__add = f("add")
  85. t.__sub = f("sub")
  86. t.__mul = f("mul")
  87. t.__div = f("div")
  88. t.__mod = f("mod")
  89. t.__unm = f("unm")
  90. t.__pow = f("pow")
  91. t.__len = f("len")
  92. assert(b+5 == b)
  93. assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==nil)
  94. assert(b+'5' == b)
  95. assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==nil)
  96. assert(5+b == 5)
  97. assert(cap[0] == "add" and cap[1] == 5 and cap[2] == b and cap[3]==nil)
  98. assert('5'+b == '5')
  99. assert(cap[0] == "add" and cap[1] == '5' and cap[2] == b and cap[3]==nil)
  100. b=b-3; assert(getmetatable(b) == t)
  101. assert(5-a == 5)
  102. assert(cap[0] == "sub" and cap[1] == 5 and cap[2] == a and cap[3]==nil)
  103. assert('5'-a == '5')
  104. assert(cap[0] == "sub" and cap[1] == '5' and cap[2] == a and cap[3]==nil)
  105. assert(a*a == a)
  106. assert(cap[0] == "mul" and cap[1] == a and cap[2] == a and cap[3]==nil)
  107. assert(a/0 == a)
  108. assert(cap[0] == "div" and cap[1] == a and cap[2] == 0 and cap[3]==nil)
  109. assert(a%2 == a)
  110. assert(cap[0] == "mod" and cap[1] == a and cap[2] == 2 and cap[3]==nil)
  111. assert(-a == a)
  112. assert(cap[0] == "unm" and cap[1] == a)
  113. assert(a^4 == a)
  114. assert(cap[0] == "pow" and cap[1] == a and cap[2] == 4 and cap[3]==nil)
  115. assert(a^'4' == a)
  116. assert(cap[0] == "pow" and cap[1] == a and cap[2] == '4' and cap[3]==nil)
  117. assert(4^a == 4)
  118. assert(cap[0] == "pow" and cap[1] == 4 and cap[2] == a and cap[3]==nil)
  119. assert('4'^a == '4')
  120. assert(cap[0] == "pow" and cap[1] == '4' and cap[2] == a and cap[3]==nil)
  121. assert(#a == a)
  122. assert(cap[0] == "len" and cap[1] == a)
  123. -- test for rawlen
  124. t = setmetatable({1,2,3}, {__len = function () return 10 end})
  125. assert(#t == 10 and rawlen(t) == 3)
  126. assert(rawlen"abc" == 3)
  127. assert(not pcall(rawlen, io.stdin))
  128. assert(not pcall(rawlen, 34))
  129. assert(not pcall(rawlen))
  130. t = {}
  131. t.__lt = function (a,b,c)
  132. collectgarbage()
  133. assert(c == nil)
  134. if type(a) == 'table' then a = a.x end
  135. if type(b) == 'table' then b = b.x end
  136. return a<b, "dummy"
  137. end
  138. function Op(x) return setmetatable({x=x}, t) end
  139. local function test ()
  140. assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1)))
  141. assert(not(1 < Op(1)) and (Op(1) < 2) and not(2 < Op(1)))
  142. assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a')))
  143. assert(not('a' < Op('a')) and (Op('a') < 'b') and not(Op('b') < Op('a')))
  144. assert((Op(1)<=Op(1)) and (Op(1)<=Op(2)) and not(Op(2)<=Op(1)))
  145. assert((Op('a')<=Op('a')) and (Op('a')<=Op('b')) and not(Op('b')<=Op('a')))
  146. assert(not(Op(1)>Op(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1)))
  147. assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a')))
  148. assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1)))
  149. assert((1 >= Op(1)) and not(1 >= Op(2)) and (Op(2) >= 1))
  150. assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a')))
  151. assert(('a' >= Op('a')) and not(Op('a') >= 'b') and (Op('b') >= Op('a')))
  152. end
  153. test()
  154. t.__le = function (a,b,c)
  155. assert(c == nil)
  156. if type(a) == 'table' then a = a.x end
  157. if type(b) == 'table' then b = b.x end
  158. return a<=b, "dummy"
  159. end
  160. test() -- retest comparisons, now using both `lt' and `le'
  161. -- test `partial order'
  162. local function Set(x)
  163. local y = {}
  164. for _,k in pairs(x) do y[k] = 1 end
  165. return setmetatable(y, t)
  166. end
  167. t.__lt = function (a,b)
  168. for k in pairs(a) do
  169. if not b[k] then return false end
  170. b[k] = nil
  171. end
  172. return next(b) ~= nil
  173. end
  174. t.__le = nil
  175. assert(Set{1,2,3} < Set{1,2,3,4})
  176. assert(not(Set{1,2,3,4} < Set{1,2,3,4}))
  177. assert((Set{1,2,3,4} <= Set{1,2,3,4}))
  178. assert((Set{1,2,3,4} >= Set{1,2,3,4}))
  179. assert((Set{1,3} <= Set{3,5})) -- wrong!! model needs a `le' method ;-)
  180. t.__le = function (a,b)
  181. for k in pairs(a) do
  182. if not b[k] then return false end
  183. end
  184. return true
  185. end
  186. assert(not (Set{1,3} <= Set{3,5})) -- now its OK!
  187. assert(not(Set{1,3} <= Set{3,5}))
  188. assert(not(Set{1,3} >= Set{3,5}))
  189. t.__eq = function (a,b)
  190. for k in pairs(a) do
  191. if not b[k] then return false end
  192. b[k] = nil
  193. end
  194. return next(b) == nil
  195. end
  196. local s = Set{1,3,5}
  197. assert(s == Set{3,5,1})
  198. assert(not rawequal(s, Set{3,5,1}))
  199. assert(rawequal(s, s))
  200. assert(Set{1,3,5,1} == Set{3,5,1})
  201. assert(Set{1,3,5} ~= Set{3,5,1,6})
  202. t[Set{1,3,5}] = 1
  203. assert(t[Set{1,3,5}] == nil) -- `__eq' is not valid for table accesses
  204. t.__concat = function (a,b,c)
  205. assert(c == nil)
  206. if type(a) == 'table' then a = a.val end
  207. if type(b) == 'table' then b = b.val end
  208. if A then return a..b
  209. else
  210. return setmetatable({val=a..b}, t)
  211. end
  212. end
  213. c = {val="c"}; setmetatable(c, t)
  214. d = {val="d"}; setmetatable(d, t)
  215. A = true
  216. assert(c..d == 'cd')
  217. assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g")
  218. A = false
  219. assert((c..d..c..d).val == 'cdcd')
  220. x = c..d
  221. assert(getmetatable(x) == t and x.val == 'cd')
  222. x = 0 .."a".."b"..c..d.."e".."f".."g"
  223. assert(x.val == "0abcdefg")
  224. -- concat metamethod x numbers (bug in 5.1.1)
  225. c = {}
  226. local x
  227. setmetatable(c, {__concat = function (a,b)
  228. assert(type(a) == "number" and b == c or type(b) == "number" and a == c)
  229. return c
  230. end})
  231. assert(c..5 == c and 5 .. c == c)
  232. assert(4 .. c .. 5 == c and 4 .. 5 .. 6 .. 7 .. c == c)
  233. -- test comparison compatibilities
  234. local t1, t2, c, d
  235. t1 = {}; c = {}; setmetatable(c, t1)
  236. d = {}
  237. t1.__eq = function () return true end
  238. t1.__lt = function () return true end
  239. setmetatable(d, t1)
  240. assert(c == d and c < d and not(d <= c))
  241. t2 = {}
  242. t2.__eq = t1.__eq
  243. t2.__lt = t1.__lt
  244. setmetatable(d, t2)
  245. assert(c == d and c < d and not(d <= c))
  246. -- test for several levels of calls
  247. local i
  248. local tt = {
  249. __call = function (t, ...)
  250. i = i+1
  251. if t.f then return t.f(...)
  252. else return {...}
  253. end
  254. end
  255. }
  256. local a = setmetatable({}, tt)
  257. local b = setmetatable({f=a}, tt)
  258. local c = setmetatable({f=b}, tt)
  259. i = 0
  260. x = c(3,4,5)
  261. assert(i == 3 and x[1] == 3 and x[3] == 5)
  262. assert(_G.X == 20)
  263. print'+'
  264. local _g = _G
  265. _ENV = setmetatable({}, {__index=function (_,k) return _g[k] end})
  266. a = {}
  267. rawset(a, "x", 1, 2, 3)
  268. assert(a.x == 1 and rawget(a, "x", 3) == 1)
  269. print '+'
  270. -- testing metatables for basic types
  271. local debug = require'debug'
  272. mt = {}
  273. debug.setmetatable(10, mt)
  274. assert(getmetatable(-2) == mt)
  275. mt.__index = function (a,b) return a+b end
  276. assert((10)[3] == 13)
  277. assert((10)["3"] == 13)
  278. debug.setmetatable(23, nil)
  279. assert(getmetatable(-2) == nil)
  280. debug.setmetatable(true, mt)
  281. assert(getmetatable(false) == mt)
  282. mt.__index = function (a,b) return a or b end
  283. assert((true)[false] == true)
  284. assert((false)[false] == false)
  285. debug.setmetatable(false, nil)
  286. assert(getmetatable(true) == nil)
  287. debug.setmetatable(nil, mt)
  288. assert(getmetatable(nil) == mt)
  289. mt.__add = function (a,b) return (a or 0) + (b or 0) end
  290. assert(10 + nil == 10)
  291. assert(nil + 23 == 23)
  292. assert(nil + nil == 0)
  293. debug.setmetatable(nil, nil)
  294. assert(getmetatable(nil) == nil)
  295. debug.setmetatable(nil, {})
  296. -- loops in delegation
  297. a = {}; setmetatable(a, a); a.__index = a; a.__newindex = a
  298. assert(not pcall(function (a,b) return a[b] end, a, 10))
  299. assert(not pcall(function (a,b,c) a[b] = c end, a, 10, true))
  300. -- bug in 5.1
  301. T, K, V = nil
  302. grandparent = {}
  303. grandparent.__newindex = function(t,k,v) T=t; K=k; V=v end
  304. parent = {}
  305. parent.__newindex = parent
  306. setmetatable(parent, grandparent)
  307. child = setmetatable({}, parent)
  308. child.foo = 10 --> CRASH (on some machines)
  309. assert(T == parent and K == "foo" and V == 10)
  310. print 'OK'
  311. return 12