coroutine.lua 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  1. -- $Id: testes/coroutine.lua $
  2. -- See Copyright Notice in file all.lua
  3. print "testing coroutines"
  4. local debug = require'debug'
  5. local f
  6. local main, ismain = coroutine.running()
  7. assert(type(main) == "thread" and ismain)
  8. assert(not coroutine.resume(main))
  9. assert(not coroutine.isyieldable(main) and not coroutine.isyieldable())
  10. assert(not pcall(coroutine.yield))
  11. -- trivial errors
  12. assert(not pcall(coroutine.resume, 0))
  13. assert(not pcall(coroutine.status, 0))
  14. -- tests for multiple yield/resume arguments
  15. local function eqtab (t1, t2)
  16. assert(#t1 == #t2)
  17. for i = 1, #t1 do
  18. local v = t1[i]
  19. assert(t2[i] == v)
  20. end
  21. end
  22. _G.x = nil -- declare x
  23. function foo (a, ...)
  24. local x, y = coroutine.running()
  25. assert(x == f and y == false)
  26. -- next call should not corrupt coroutine (but must fail,
  27. -- as it attempts to resume the running coroutine)
  28. assert(coroutine.resume(f) == false)
  29. assert(coroutine.status(f) == "running")
  30. local arg = {...}
  31. assert(coroutine.isyieldable(x))
  32. for i=1,#arg do
  33. _G.x = {coroutine.yield(table.unpack(arg[i]))}
  34. end
  35. return table.unpack(a)
  36. end
  37. f = coroutine.create(foo)
  38. assert(coroutine.isyieldable(f))
  39. assert(type(f) == "thread" and coroutine.status(f) == "suspended")
  40. assert(string.find(tostring(f), "thread"))
  41. local s,a,b,c,d
  42. s,a,b,c,d = coroutine.resume(f, {1,2,3}, {}, {1}, {'a', 'b', 'c'})
  43. assert(coroutine.isyieldable(f))
  44. assert(s and a == nil and coroutine.status(f) == "suspended")
  45. s,a,b,c,d = coroutine.resume(f)
  46. eqtab(_G.x, {})
  47. assert(s and a == 1 and b == nil)
  48. assert(coroutine.isyieldable(f))
  49. s,a,b,c,d = coroutine.resume(f, 1, 2, 3)
  50. eqtab(_G.x, {1, 2, 3})
  51. assert(s and a == 'a' and b == 'b' and c == 'c' and d == nil)
  52. s,a,b,c,d = coroutine.resume(f, "xuxu")
  53. eqtab(_G.x, {"xuxu"})
  54. assert(s and a == 1 and b == 2 and c == 3 and d == nil)
  55. assert(coroutine.status(f) == "dead")
  56. s, a = coroutine.resume(f, "xuxu")
  57. assert(not s and string.find(a, "dead") and coroutine.status(f) == "dead")
  58. -- yields in tail calls
  59. local function foo (i) return coroutine.yield(i) end
  60. f = coroutine.wrap(function ()
  61. for i=1,10 do
  62. assert(foo(i) == _G.x)
  63. end
  64. return 'a'
  65. end)
  66. for i=1,10 do _G.x = i; assert(f(i) == i) end
  67. _G.x = 'xuxu'; assert(f('xuxu') == 'a')
  68. -- recursive
  69. function pf (n, i)
  70. coroutine.yield(n)
  71. pf(n*i, i+1)
  72. end
  73. f = coroutine.wrap(pf)
  74. local s=1
  75. for i=1,10 do
  76. assert(f(1, 1) == s)
  77. s = s*i
  78. end
  79. -- sieve
  80. function gen (n)
  81. return coroutine.wrap(function ()
  82. for i=2,n do coroutine.yield(i) end
  83. end)
  84. end
  85. function filter (p, g)
  86. return coroutine.wrap(function ()
  87. while 1 do
  88. local n = g()
  89. if n == nil then return end
  90. if math.fmod(n, p) ~= 0 then coroutine.yield(n) end
  91. end
  92. end)
  93. end
  94. local x = gen(80)
  95. local a = {}
  96. while 1 do
  97. local n = x()
  98. if n == nil then break end
  99. table.insert(a, n)
  100. x = filter(n, x)
  101. end
  102. assert(#a == 22 and a[#a] == 79)
  103. x, a = nil
  104. -- coroutine closing
  105. local function func2close (f)
  106. return setmetatable({}, {__close = f})
  107. end
  108. do
  109. -- ok to close a dead coroutine
  110. local co = coroutine.create(print)
  111. assert(coroutine.resume(co, "testing 'coroutine.close'"))
  112. assert(coroutine.status(co) == "dead")
  113. assert(coroutine.close(co))
  114. -- cannot close the running coroutine
  115. local st, msg = pcall(coroutine.close, coroutine.running())
  116. assert(not st and string.find(msg, "running"))
  117. local main = coroutine.running()
  118. -- cannot close a "normal" coroutine
  119. ;(coroutine.wrap(function ()
  120. local st, msg = pcall(coroutine.close, main)
  121. assert(not st and string.find(msg, "normal"))
  122. end))()
  123. -- to-be-closed variables in coroutines
  124. local X
  125. co = coroutine.create(function ()
  126. local x <close> = func2close(function (self, err)
  127. assert(err == nil); X = false
  128. end)
  129. X = true
  130. coroutine.yield()
  131. end)
  132. coroutine.resume(co)
  133. assert(X)
  134. assert(coroutine.close(co))
  135. assert(not X and coroutine.status(co) == "dead")
  136. -- error closing a coroutine
  137. warn("@on")
  138. local x = 0
  139. co = coroutine.create(function()
  140. local y <close> = func2close(function (self,err)
  141. if (err ~= 111) then os.exit(false) end -- should not happen
  142. x = 200
  143. error("200")
  144. end)
  145. local x <close> = func2close(function (self, err)
  146. assert(err == nil); error(111)
  147. end)
  148. coroutine.yield()
  149. end)
  150. coroutine.resume(co)
  151. assert(x == 0)
  152. -- with test library, use 'store' mode to check warnings
  153. warn(not T and "@off" or "@store")
  154. local st, msg = coroutine.close(co)
  155. if not T then
  156. warn("@on")
  157. else -- test library
  158. assert(string.find(_WARN, "200")); _WARN = false
  159. warn("@normal")
  160. end
  161. assert(st == false and coroutine.status(co) == "dead" and msg == 111)
  162. assert(x == 200)
  163. end
  164. do
  165. -- <close> versus pcall in coroutines
  166. local X = false
  167. local Y = false
  168. function foo ()
  169. local x <close> = func2close(function (self, err)
  170. Y = debug.getinfo(2)
  171. X = err
  172. end)
  173. error(43)
  174. end
  175. co = coroutine.create(function () return pcall(foo) end)
  176. local st1, st2, err = coroutine.resume(co)
  177. assert(st1 and not st2 and err == 43)
  178. assert(X == 43 and Y.name == "pcall")
  179. end
  180. -- yielding across C boundaries
  181. co = coroutine.wrap(function()
  182. assert(not pcall(table.sort,{1,2,3}, coroutine.yield))
  183. assert(coroutine.isyieldable())
  184. coroutine.yield(20)
  185. return 30
  186. end)
  187. assert(co() == 20)
  188. assert(co() == 30)
  189. local f = function (s, i) return coroutine.yield(i) end
  190. local f1 = coroutine.wrap(function ()
  191. return xpcall(pcall, function (...) return ... end,
  192. function ()
  193. local s = 0
  194. for i in f, nil, 1 do pcall(function () s = s + i end) end
  195. error({s})
  196. end)
  197. end)
  198. f1()
  199. for i = 1, 10 do assert(f1(i) == i) end
  200. local r1, r2, v = f1(nil)
  201. assert(r1 and not r2 and v[1] == (10 + 1)*10/2)
  202. function f (a, b) a = coroutine.yield(a); error{a + b} end
  203. function g(x) return x[1]*2 end
  204. co = coroutine.wrap(function ()
  205. coroutine.yield(xpcall(f, g, 10, 20))
  206. end)
  207. assert(co() == 10)
  208. r, msg = co(100)
  209. assert(not r and msg == 240)
  210. -- unyieldable C call
  211. do
  212. local function f (c)
  213. assert(not coroutine.isyieldable())
  214. return c .. c
  215. end
  216. local co = coroutine.wrap(function (c)
  217. assert(coroutine.isyieldable())
  218. local s = string.gsub("a", ".", f)
  219. return s
  220. end)
  221. assert(co() == "aa")
  222. end
  223. do -- testing single trace of coroutines
  224. local X
  225. local co = coroutine.create(function ()
  226. coroutine.yield(10)
  227. return 20;
  228. end)
  229. local trace = {}
  230. local function dotrace (event)
  231. trace[#trace + 1] = event
  232. end
  233. debug.sethook(co, dotrace, "clr")
  234. repeat until not coroutine.resume(co)
  235. local correcttrace = {"call", "line", "call", "return", "line", "return"}
  236. assert(#trace == #correcttrace)
  237. for k, v in pairs(trace) do
  238. assert(v == correcttrace[k])
  239. end
  240. end
  241. -- errors in coroutines
  242. function foo ()
  243. assert(debug.getinfo(1).currentline == debug.getinfo(foo).linedefined + 1)
  244. assert(debug.getinfo(2).currentline == debug.getinfo(goo).linedefined)
  245. coroutine.yield(3)
  246. error(foo)
  247. end
  248. function goo() foo() end
  249. x = coroutine.wrap(goo)
  250. assert(x() == 3)
  251. local a,b = pcall(x)
  252. assert(not a and b == foo)
  253. x = coroutine.create(goo)
  254. a,b = coroutine.resume(x)
  255. assert(a and b == 3)
  256. a,b = coroutine.resume(x)
  257. assert(not a and b == foo and coroutine.status(x) == "dead")
  258. a,b = coroutine.resume(x)
  259. assert(not a and string.find(b, "dead") and coroutine.status(x) == "dead")
  260. -- co-routines x for loop
  261. function all (a, n, k)
  262. if k == 0 then coroutine.yield(a)
  263. else
  264. for i=1,n do
  265. a[k] = i
  266. all(a, n, k-1)
  267. end
  268. end
  269. end
  270. local a = 0
  271. for t in coroutine.wrap(function () all({}, 5, 4) end) do
  272. a = a+1
  273. end
  274. assert(a == 5^4)
  275. -- access to locals of collected corroutines
  276. local C = {}; setmetatable(C, {__mode = "kv"})
  277. local x = coroutine.wrap (function ()
  278. local a = 10
  279. local function f () a = a+10; return a end
  280. while true do
  281. a = a+1
  282. coroutine.yield(f)
  283. end
  284. end)
  285. C[1] = x;
  286. local f = x()
  287. assert(f() == 21 and x()() == 32 and x() == f)
  288. x = nil
  289. collectgarbage()
  290. assert(C[1] == undef)
  291. assert(f() == 43 and f() == 53)
  292. -- old bug: attempt to resume itself
  293. function co_func (current_co)
  294. assert(coroutine.running() == current_co)
  295. assert(coroutine.resume(current_co) == false)
  296. coroutine.yield(10, 20)
  297. assert(coroutine.resume(current_co) == false)
  298. coroutine.yield(23)
  299. return 10
  300. end
  301. local co = coroutine.create(co_func)
  302. local a,b,c = coroutine.resume(co, co)
  303. assert(a == true and b == 10 and c == 20)
  304. a,b = coroutine.resume(co, co)
  305. assert(a == true and b == 23)
  306. a,b = coroutine.resume(co, co)
  307. assert(a == true and b == 10)
  308. assert(coroutine.resume(co, co) == false)
  309. assert(coroutine.resume(co, co) == false)
  310. -- other old bug when attempting to resume itself
  311. -- (trigger C-code assertions)
  312. do
  313. local A = coroutine.running()
  314. local B = coroutine.create(function() return coroutine.resume(A) end)
  315. local st, res = coroutine.resume(B)
  316. assert(st == true and res == false)
  317. local X = false
  318. A = coroutine.wrap(function()
  319. local _ <close> = setmetatable({}, {__close = function () X = true end})
  320. return pcall(A, 1)
  321. end)
  322. st, res = A()
  323. assert(not st and string.find(res, "non%-suspended") and X == true)
  324. end
  325. -- attempt to resume 'normal' coroutine
  326. local co1, co2
  327. co1 = coroutine.create(function () return co2() end)
  328. co2 = coroutine.wrap(function ()
  329. assert(coroutine.status(co1) == 'normal')
  330. assert(not coroutine.resume(co1))
  331. coroutine.yield(3)
  332. end)
  333. a,b = coroutine.resume(co1)
  334. assert(a and b == 3)
  335. assert(coroutine.status(co1) == 'dead')
  336. -- infinite recursion of coroutines
  337. a = function(a) coroutine.wrap(a)(a) end
  338. assert(not pcall(a, a))
  339. a = nil
  340. -- access to locals of erroneous coroutines
  341. local x = coroutine.create (function ()
  342. local a = 10
  343. _G.f = function () a=a+1; return a end
  344. error('x')
  345. end)
  346. assert(not coroutine.resume(x))
  347. -- overwrite previous position of local `a'
  348. assert(not coroutine.resume(x, 1, 1, 1, 1, 1, 1, 1))
  349. assert(_G.f() == 11)
  350. assert(_G.f() == 12)
  351. if not T then
  352. (Message or print)
  353. ('\n >>> testC not active: skipping coroutine API tests <<<\n')
  354. else
  355. print "testing yields inside hooks"
  356. local turn
  357. function fact (t, x)
  358. assert(turn == t)
  359. if x == 0 then return 1
  360. else return x*fact(t, x-1)
  361. end
  362. end
  363. local A, B = 0, 0
  364. local x = coroutine.create(function ()
  365. T.sethook("yield 0", "", 2)
  366. A = fact("A", 6)
  367. end)
  368. local y = coroutine.create(function ()
  369. T.sethook("yield 0", "", 3)
  370. B = fact("B", 7)
  371. end)
  372. while A==0 or B==0 do -- A ~= 0 when 'x' finishes (similar for 'B','y')
  373. if A==0 then turn = "A"; assert(T.resume(x)) end
  374. if B==0 then turn = "B"; assert(T.resume(y)) end
  375. -- check that traceback works correctly after yields inside hooks
  376. debug.traceback(x)
  377. debug.traceback(y)
  378. end
  379. assert(B // A == 7) -- fact(7) // fact(6)
  380. local line = debug.getinfo(1, "l").currentline + 2 -- get line number
  381. local function foo ()
  382. local x = 10 --<< this line is 'line'
  383. x = x + 10
  384. _G.XX = x
  385. end
  386. -- testing yields in line hook
  387. local co = coroutine.wrap(function ()
  388. T.sethook("setglobal X; yield 0", "l", 0); foo(); return 10 end)
  389. _G.XX = nil;
  390. _G.X = nil; co(); assert(_G.X == line)
  391. _G.X = nil; co(); assert(_G.X == line + 1)
  392. _G.X = nil; co(); assert(_G.X == line + 2 and _G.XX == nil)
  393. _G.X = nil; co(); assert(_G.X == line + 3 and _G.XX == 20)
  394. assert(co() == 10)
  395. -- testing yields in count hook
  396. co = coroutine.wrap(function ()
  397. T.sethook("yield 0", "", 1); foo(); return 10 end)
  398. _G.XX = nil;
  399. local c = 0
  400. repeat c = c + 1; local a = co() until a == 10
  401. assert(_G.XX == 20 and c >= 5)
  402. co = coroutine.wrap(function ()
  403. T.sethook("yield 0", "", 2); foo(); return 10 end)
  404. _G.XX = nil;
  405. local c = 0
  406. repeat c = c + 1; local a = co() until a == 10
  407. assert(_G.XX == 20 and c >= 5)
  408. _G.X = nil; _G.XX = nil
  409. do
  410. -- testing debug library on a coroutine suspended inside a hook
  411. -- (bug in 5.2/5.3)
  412. c = coroutine.create(function (a, ...)
  413. T.sethook("yield 0", "l") -- will yield on next two lines
  414. assert(a == 10)
  415. return ...
  416. end)
  417. assert(coroutine.resume(c, 1, 2, 3)) -- start coroutine
  418. local n,v = debug.getlocal(c, 0, 1) -- check its local
  419. assert(n == "a" and v == 1)
  420. assert(debug.setlocal(c, 0, 1, 10)) -- test 'setlocal'
  421. local t = debug.getinfo(c, 0) -- test 'getinfo'
  422. assert(t.currentline == t.linedefined + 1)
  423. assert(not debug.getinfo(c, 1)) -- no other level
  424. assert(coroutine.resume(c)) -- run next line
  425. v = {coroutine.resume(c)} -- finish coroutine
  426. assert(v[1] == true and v[2] == 2 and v[3] == 3 and v[4] == undef)
  427. assert(not coroutine.resume(c))
  428. end
  429. do
  430. -- testing debug library on last function in a suspended coroutine
  431. -- (bug in 5.2/5.3)
  432. local c = coroutine.create(function () T.testC("yield 1", 10, 20) end)
  433. local a, b = coroutine.resume(c)
  434. assert(a and b == 20)
  435. assert(debug.getinfo(c, 0).linedefined == -1)
  436. a, b = debug.getlocal(c, 0, 2)
  437. assert(b == 10)
  438. end
  439. print "testing coroutine API"
  440. -- reusing a thread
  441. assert(T.testC([[
  442. newthread # create thread
  443. pushvalue 2 # push body
  444. pushstring 'a a a' # push argument
  445. xmove 0 3 2 # move values to new thread
  446. resume -1, 1 # call it first time
  447. pushstatus
  448. xmove 3 0 0 # move results back to stack
  449. setglobal X # result
  450. setglobal Y # status
  451. pushvalue 2 # push body (to call it again)
  452. pushstring 'b b b'
  453. xmove 0 3 2
  454. resume -1, 1 # call it again
  455. pushstatus
  456. xmove 3 0 0
  457. return 1 # return result
  458. ]], function (...) return ... end) == 'b b b')
  459. assert(X == 'a a a' and Y == 'OK')
  460. -- resuming running coroutine
  461. C = coroutine.create(function ()
  462. return T.testC([[
  463. pushnum 10;
  464. pushnum 20;
  465. resume -3 2;
  466. pushstatus
  467. gettop;
  468. return 3]], C)
  469. end)
  470. local a, b, c, d = coroutine.resume(C)
  471. assert(a == true and string.find(b, "non%-suspended") and
  472. c == "ERRRUN" and d == 4)
  473. a, b, c, d = T.testC([[
  474. rawgeti R 1 # get main thread
  475. pushnum 10;
  476. pushnum 20;
  477. resume -3 2;
  478. pushstatus
  479. gettop;
  480. return 4]])
  481. assert(a == coroutine.running() and string.find(b, "non%-suspended") and
  482. c == "ERRRUN" and d == 4)
  483. -- using a main thread as a coroutine (dubious use!)
  484. local state = T.newstate()
  485. -- check that yielddable is working correctly
  486. assert(T.testC(state, "newthread; isyieldable -1; remove 1; return 1"))
  487. -- main thread is not yieldable
  488. assert(not T.testC(state, "rawgeti R 1; isyieldable -1; remove 1; return 1"))
  489. T.testC(state, "settop 0")
  490. T.loadlib(state)
  491. assert(T.doremote(state, [[
  492. coroutine = require'coroutine';
  493. X = function (x) coroutine.yield(x, 'BB'); return 'CC' end;
  494. return 'ok']]))
  495. t = table.pack(T.testC(state, [[
  496. rawgeti R 1 # get main thread
  497. pushstring 'XX'
  498. getglobal X # get function for body
  499. pushstring AA # arg
  500. resume 1 1 # 'resume' shadows previous stack!
  501. gettop
  502. setglobal T # top
  503. setglobal B # second yielded value
  504. setglobal A # fist yielded value
  505. rawgeti R 1 # get main thread
  506. pushnum 5 # arg (noise)
  507. resume 1 1 # after coroutine ends, previous stack is back
  508. pushstatus
  509. return *
  510. ]]))
  511. assert(t.n == 4 and t[2] == 'XX' and t[3] == 'CC' and t[4] == 'OK')
  512. assert(T.doremote(state, "return T") == '2')
  513. assert(T.doremote(state, "return A") == 'AA')
  514. assert(T.doremote(state, "return B") == 'BB')
  515. T.closestate(state)
  516. print'+'
  517. end
  518. -- leaving a pending coroutine open
  519. _X = coroutine.wrap(function ()
  520. local a = 10
  521. local x = function () a = a+1 end
  522. coroutine.yield()
  523. end)
  524. _X()
  525. if not _soft then
  526. -- bug (stack overflow)
  527. local j = 2^9
  528. local lim = 1000000 -- (C stack limit; assume 32-bit machine)
  529. local t = {lim - 10, lim - 5, lim - 1, lim, lim + 1}
  530. for i = 1, #t do
  531. local j = t[i]
  532. co = coroutine.create(function()
  533. local t = {}
  534. for i = 1, j do t[i] = i end
  535. return table.unpack(t)
  536. end)
  537. local r, msg = coroutine.resume(co)
  538. assert(not r)
  539. end
  540. co = nil
  541. end
  542. assert(coroutine.running() == main)
  543. print"+"
  544. print"testing yields inside metamethods"
  545. local function val(x)
  546. if type(x) == "table" then return x.x else return x end
  547. end
  548. local mt = {
  549. __eq = function(a,b) coroutine.yield(nil, "eq"); return val(a) == val(b) end,
  550. __lt = function(a,b) coroutine.yield(nil, "lt"); return val(a) < val(b) end,
  551. __le = function(a,b) coroutine.yield(nil, "le"); return a - b <= 0 end,
  552. __add = function(a,b) coroutine.yield(nil, "add");
  553. return val(a) + val(b) end,
  554. __sub = function(a,b) coroutine.yield(nil, "sub"); return val(a) - val(b) end,
  555. __mul = function(a,b) coroutine.yield(nil, "mul"); return val(a) * val(b) end,
  556. __div = function(a,b) coroutine.yield(nil, "div"); return val(a) / val(b) end,
  557. __idiv = function(a,b) coroutine.yield(nil, "idiv");
  558. return val(a) // val(b) end,
  559. __pow = function(a,b) coroutine.yield(nil, "pow"); return val(a) ^ val(b) end,
  560. __mod = function(a,b) coroutine.yield(nil, "mod"); return val(a) % val(b) end,
  561. __unm = function(a,b) coroutine.yield(nil, "unm"); return -val(a) end,
  562. __bnot = function(a,b) coroutine.yield(nil, "bnot"); return ~val(a) end,
  563. __shl = function(a,b) coroutine.yield(nil, "shl");
  564. return val(a) << val(b) end,
  565. __shr = function(a,b) coroutine.yield(nil, "shr");
  566. return val(a) >> val(b) end,
  567. __band = function(a,b)
  568. coroutine.yield(nil, "band")
  569. return val(a) & val(b)
  570. end,
  571. __bor = function(a,b) coroutine.yield(nil, "bor");
  572. return val(a) | val(b) end,
  573. __bxor = function(a,b) coroutine.yield(nil, "bxor");
  574. return val(a) ~ val(b) end,
  575. __concat = function(a,b)
  576. coroutine.yield(nil, "concat");
  577. return val(a) .. val(b)
  578. end,
  579. __index = function (t,k) coroutine.yield(nil, "idx"); return t.k[k] end,
  580. __newindex = function (t,k,v) coroutine.yield(nil, "nidx"); t.k[k] = v end,
  581. }
  582. local function new (x)
  583. return setmetatable({x = x, k = {}}, mt)
  584. end
  585. local a = new(10)
  586. local b = new(12)
  587. local c = new"hello"
  588. local function run (f, t)
  589. local i = 1
  590. local c = coroutine.wrap(f)
  591. while true do
  592. local res, stat = c()
  593. if res then assert(t[i] == undef); return res, t end
  594. assert(stat == t[i])
  595. i = i + 1
  596. end
  597. end
  598. assert(run(function () if (a>=b) then return '>=' else return '<' end end,
  599. {"le", "sub"}) == "<")
  600. assert(run(function () if (a<=b) then return '<=' else return '>' end end,
  601. {"le", "sub"}) == "<=")
  602. assert(run(function () if (a==b) then return '==' else return '~=' end end,
  603. {"eq"}) == "~=")
  604. assert(run(function () return a & b + a end, {"add", "band"}) == 2)
  605. assert(run(function () return 1 + a end, {"add"}) == 11)
  606. assert(run(function () return a - 25 end, {"sub"}) == -15)
  607. assert(run(function () return 2 * a end, {"mul"}) == 20)
  608. assert(run(function () return a ^ 2 end, {"pow"}) == 100)
  609. assert(run(function () return a / 2 end, {"div"}) == 5)
  610. assert(run(function () return a % 6 end, {"mod"}) == 4)
  611. assert(run(function () return a // 3 end, {"idiv"}) == 3)
  612. assert(run(function () return a + b end, {"add"}) == 22)
  613. assert(run(function () return a - b end, {"sub"}) == -2)
  614. assert(run(function () return a * b end, {"mul"}) == 120)
  615. assert(run(function () return a ^ b end, {"pow"}) == 10^12)
  616. assert(run(function () return a / b end, {"div"}) == 10/12)
  617. assert(run(function () return a % b end, {"mod"}) == 10)
  618. assert(run(function () return a // b end, {"idiv"}) == 0)
  619. -- repeat tests with larger constants (to use 'K' opcodes)
  620. local a1000 = new(1000)
  621. assert(run(function () return a1000 + 1000 end, {"add"}) == 2000)
  622. assert(run(function () return a1000 - 25000 end, {"sub"}) == -24000)
  623. assert(run(function () return 2000 * a end, {"mul"}) == 20000)
  624. assert(run(function () return a1000 / 1000 end, {"div"}) == 1)
  625. assert(run(function () return a1000 % 600 end, {"mod"}) == 400)
  626. assert(run(function () return a1000 // 500 end, {"idiv"}) == 2)
  627. assert(run(function () return a % b end, {"mod"}) == 10)
  628. assert(run(function () return ~a & b end, {"bnot", "band"}) == ~10 & 12)
  629. assert(run(function () return a | b end, {"bor"}) == 10 | 12)
  630. assert(run(function () return a ~ b end, {"bxor"}) == 10 ~ 12)
  631. assert(run(function () return a << b end, {"shl"}) == 10 << 12)
  632. assert(run(function () return a >> b end, {"shr"}) == 10 >> 12)
  633. assert(run(function () return 10 & b end, {"band"}) == 10 & 12)
  634. assert(run(function () return a | 2 end, {"bor"}) == 10 | 2)
  635. assert(run(function () return a ~ 2 end, {"bxor"}) == 10 ~ 2)
  636. assert(run(function () return a >> 2 end, {"shr"}) == 10 >> 2)
  637. assert(run(function () return 1 >> a end, {"shr"}) == 1 >> 10)
  638. assert(run(function () return a << 2 end, {"shl"}) == 10 << 2)
  639. assert(run(function () return 1 << a end, {"shl"}) == 1 << 10)
  640. assert(run(function () return 2 ~ a end, {"bxor"}) == 2 ~ 10)
  641. assert(run(function () return a..b end, {"concat"}) == "1012")
  642. assert(run(function() return a .. b .. c .. a end,
  643. {"concat", "concat", "concat"}) == "1012hello10")
  644. assert(run(function() return "a" .. "b" .. a .. "c" .. c .. b .. "x" end,
  645. {"concat", "concat", "concat"}) == "ab10chello12x")
  646. do -- a few more tests for comparison operators
  647. local mt1 = {
  648. __le = function (a,b)
  649. coroutine.yield(10)
  650. return (val(a) <= val(b))
  651. end,
  652. __lt = function (a,b)
  653. coroutine.yield(10)
  654. return val(a) < val(b)
  655. end,
  656. }
  657. local mt2 = { __lt = mt1.__lt, __le = mt1.__le }
  658. local function run (f)
  659. local co = coroutine.wrap(f)
  660. local res
  661. repeat
  662. res = co()
  663. until res ~= 10
  664. return res
  665. end
  666. local function test ()
  667. local a1 = setmetatable({x=1}, mt1)
  668. local a2 = setmetatable({x=2}, mt2)
  669. assert(a1 < a2)
  670. assert(a1 <= a2)
  671. assert(1 < a2)
  672. assert(1 <= a2)
  673. assert(2 > a1)
  674. assert(2 >= a2)
  675. return true
  676. end
  677. run(test)
  678. end
  679. assert(run(function ()
  680. a.BB = print
  681. return a.BB
  682. end, {"nidx", "idx"}) == print)
  683. -- getuptable & setuptable
  684. do local _ENV = _ENV
  685. f = function () AAA = BBB + 1; return AAA end
  686. end
  687. g = new(10); g.k.BBB = 10;
  688. debug.setupvalue(f, 1, g)
  689. assert(run(f, {"idx", "nidx", "idx"}) == 11)
  690. assert(g.k.AAA == 11)
  691. print"+"
  692. print"testing yields inside 'for' iterators"
  693. local f = function (s, i)
  694. if i%2 == 0 then coroutine.yield(nil, "for") end
  695. if i < s then return i + 1 end
  696. end
  697. assert(run(function ()
  698. local s = 0
  699. for i in f, 4, 0 do s = s + i end
  700. return s
  701. end, {"for", "for", "for"}) == 10)
  702. -- tests for coroutine API
  703. if T==nil then
  704. (Message or print)('\n >>> testC not active: skipping coroutine API tests <<<\n')
  705. print "OK"; return
  706. end
  707. print('testing coroutine API')
  708. local function apico (...)
  709. local x = {...}
  710. return coroutine.wrap(function ()
  711. return T.testC(table.unpack(x))
  712. end)
  713. end
  714. local a = {apico(
  715. [[
  716. pushstring errorcode
  717. pcallk 1 0 2;
  718. invalid command (should not arrive here)
  719. ]],
  720. [[return *]],
  721. "stackmark",
  722. error
  723. )()}
  724. assert(#a == 4 and
  725. a[3] == "stackmark" and
  726. a[4] == "errorcode" and
  727. _G.status == "ERRRUN" and
  728. _G.ctx == 2) -- 'ctx' to pcallk
  729. local co = apico(
  730. "pushvalue 2; pushnum 10; pcallk 1 2 3; invalid command;",
  731. coroutine.yield,
  732. "getglobal status; getglobal ctx; pushvalue 2; pushstring a; pcallk 1 0 4; invalid command",
  733. "getglobal status; getglobal ctx; return *")
  734. assert(co() == 10)
  735. assert(co(20, 30) == 'a')
  736. a = {co()}
  737. assert(#a == 10 and
  738. a[2] == coroutine.yield and
  739. a[5] == 20 and a[6] == 30 and
  740. a[7] == "YIELD" and a[8] == 3 and
  741. a[9] == "YIELD" and a[10] == 4)
  742. assert(not pcall(co)) -- coroutine is dead now
  743. f = T.makeCfunc("pushnum 3; pushnum 5; yield 1;")
  744. co = coroutine.wrap(function ()
  745. assert(f() == 23); assert(f() == 23); return 10
  746. end)
  747. assert(co(23,16) == 5)
  748. assert(co(23,16) == 5)
  749. assert(co(23,16) == 10)
  750. -- testing coroutines with C bodies
  751. f = T.makeCfunc([[
  752. pushnum 102
  753. yieldk 1 U2
  754. cannot be here!
  755. ]],
  756. [[ # continuation
  757. pushvalue U3 # accessing upvalues inside a continuation
  758. pushvalue U4
  759. return *
  760. ]], 23, "huu")
  761. x = coroutine.wrap(f)
  762. assert(x() == 102)
  763. eqtab({x()}, {23, "huu"})
  764. f = T.makeCfunc[[pushstring 'a'; pushnum 102; yield 2; ]]
  765. a, b, c, d = T.testC([[newthread; pushvalue 2; xmove 0 3 1; resume 3 0;
  766. pushstatus; xmove 3 0 0; resume 3 0; pushstatus;
  767. return 4; ]], f)
  768. assert(a == 'YIELD' and b == 'a' and c == 102 and d == 'OK')
  769. -- testing chain of suspendable C calls
  770. local count = 3 -- number of levels
  771. f = T.makeCfunc([[
  772. remove 1; # remove argument
  773. pushvalue U3; # get selection function
  774. call 0 1; # call it (result is 'f' or 'yield')
  775. pushstring hello # single argument for selected function
  776. pushupvalueindex 2; # index of continuation program
  777. callk 1 -1 .; # call selected function
  778. errorerror # should never arrive here
  779. ]],
  780. [[
  781. # continuation program
  782. pushnum 34 # return value
  783. return * # return all results
  784. ]],
  785. function () -- selection function
  786. count = count - 1
  787. if count == 0 then return coroutine.yield
  788. else return f
  789. end
  790. end
  791. )
  792. co = coroutine.wrap(function () return f(nil) end)
  793. assert(co() == "hello") -- argument to 'yield'
  794. a = {co()}
  795. -- three '34's (one from each pending C call)
  796. assert(#a == 3 and a[1] == a[2] and a[2] == a[3] and a[3] == 34)
  797. -- testing yields with continuations
  798. co = coroutine.wrap(function (...) return
  799. T.testC([[ # initial function
  800. yieldk 1 2
  801. cannot be here!
  802. ]],
  803. [[ # 1st continuation
  804. yieldk 0 3
  805. cannot be here!
  806. ]],
  807. [[ # 2nd continuation
  808. yieldk 0 4
  809. cannot be here!
  810. ]],
  811. [[ # 3th continuation
  812. pushvalue 6 # function which is last arg. to 'testC' here
  813. pushnum 10; pushnum 20;
  814. pcall 2 0 0 # call should throw an error and return to next line
  815. pop 1 # remove error message
  816. pushvalue 6
  817. getglobal status; getglobal ctx
  818. pcallk 2 2 5 # call should throw an error and jump to continuation
  819. cannot be here!
  820. ]],
  821. [[ # 4th (and last) continuation
  822. return *
  823. ]],
  824. -- function called by 3th continuation
  825. function (a,b) x=a; y=b; error("errmsg") end,
  826. ...
  827. )
  828. end)
  829. local a = {co(3,4,6)}
  830. assert(a[1] == 6 and a[2] == undef)
  831. a = {co()}; assert(a[1] == undef and _G.status == "YIELD" and _G.ctx == 2)
  832. a = {co()}; assert(a[1] == undef and _G.status == "YIELD" and _G.ctx == 3)
  833. a = {co(7,8)};
  834. -- original arguments
  835. assert(type(a[1]) == 'string' and type(a[2]) == 'string' and
  836. type(a[3]) == 'string' and type(a[4]) == 'string' and
  837. type(a[5]) == 'string' and type(a[6]) == 'function')
  838. -- arguments left from fist resume
  839. assert(a[7] == 3 and a[8] == 4)
  840. -- arguments to last resume
  841. assert(a[9] == 7 and a[10] == 8)
  842. -- error message and nothing more
  843. assert(a[11]:find("errmsg") and #a == 11)
  844. -- check arguments to pcallk
  845. assert(x == "YIELD" and y == 4)
  846. assert(not pcall(co)) -- coroutine should be dead
  847. -- bug in nCcalls
  848. local co = coroutine.wrap(function ()
  849. local a = {pcall(pcall,pcall,pcall,pcall,pcall,pcall,pcall,error,"hi")}
  850. return pcall(assert, table.unpack(a))
  851. end)
  852. local a = {co()}
  853. assert(a[10] == "hi")
  854. print'OK'