events.lua 8.5 KB

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