local create = coroutine.create
local wrap = coroutine.wrap
local resume = coroutine.resume
local yield = coroutine.yield
do wrap(function()
local co = create(function()
yield(string.byte(string.rep(" ", 100), 1, 100))
end)
assert(select('#', resume(co)) == 101)
end)()
end
do wrap(function()
local f = wrap(function()
yield(string.byte(string.rep(" ", 100), 1, 100))
end)
assert(select('#', f()) == 100)
end)()
end
do local function cogen(x)
return wrap(function(n) repeat x = x+n; n = yield(x) until false end),
wrap(function(n) repeat x = x*n; n = yield(x) until false end)
end
local a,b=cogen(3)
local c,d=cogen(5)
assert(d(b(c(a(d(b(c(a(1)))))))) == 168428160)
end
do local function verify(what, expect, ...)
local got = {...}
for i=1,100 do
if expect[i] ~= got[i] then
error("FAIL " .. what)
end
if expect[i] == nil then
break
end
end
end
local function cofunc(...)
verify("call", { 1, "foo" }, ...)
verify("yield", { "bar" }, yield(2, "test"))
verify("pcall yield", { true, "again" }, pcall(yield, "from pcall"))
return "end"
end
local co = create(cofunc)
verify("resume", { true, 2, "test" }, resume(co, 1, "foo"))
verify("resume pcall", { true, "from pcall" }, resume(co, "bar"))
verify("resume end", { true, "end" }, resume(co, "again"))
end
do local function verify(expect, func, ...)
local co = create(func)
for i=1,100 do
local ok, res = resume(co, ...)
if not ok then
if expect[i] ~= nil then
error("too few results: ["..i.."] = "..tostring(expect[i]).." (got: "..tostring(res)..")")
end
break
end
if expect[i] ~= res then
error("bad result: ["..i.."] = "..tostring(res).." (should be: "..tostring(expect[i])..")")
end
end
end
verify({ 42, 99 },
function(x) pcall(yield, x) return 99 end,
42)
verify({ 42, 99 },
function(x) pcall(function(y) yield(y) end, x) return 99 end,
42)
verify({ 42, 99 },
function(x) xpcall(yield, debug.traceback, x) return 99 end,
42)
verify({ 45, 44, 43, 42, 99 },
function(x, y)
for i in
function(o, k)
yield(o+k)
if k ~= 0 then return k-1 end
end,x,y do
end
return 99
end,
42, 3)
verify({ 84, 99 },
function(x)
local o = setmetatable({ x },
{__add = function(a, b) yield(a[1]+b[1]) return 99 end })
return o+o
end,
42)
end