-- stack.lua local type, select, error, coyield, cowrap, corunning = type, select, error, coroutine.yield, coroutine.wrap, coroutine.running local dummy = {} -- simple dummy local func = {} function func.push(f, op, val, self, modcount, ...) local nop, nv = coyield() return f(nop, nv, self, modcount + 1, val, ...) end function func.pop(f, op, val, self, modcount, ...) local nop, nv = coyield((...)) return f(nop, nv, self, modcount + 1, select(2, ...)) end function func.peek(f, op, val, self, modcount, ...) local nop, nv = coyield((...)) return f(nop, nv, self, modcount + 1, ...) end function func.iter(f, op, val, self, modcount, ...) local nop, nv = coyield(self, modcount, 0) return f(nop, nv, self, modcount, ...) end local function stack(op, val, self, modcount, ...) if op == dummy and val == dummy then local nop, nv = coyield() return stack(nop, nv, self, modcount, ...) end if type(op) == "number" and type(val) == "number" then -- iterator if op ~= modcount then error("modified while iterating") end local val = val + 1 if val > select("#", ...) then return nil end local v = select(val, ...) local nop, nv = coyield(val, v) return stack(nop, nv, self, modcount, ...) end return func[op](stack, op, val, self, modcount, ...) end local function newstack(...) local s = cowrap(stack) s(dummy, dummy, s, 0, ...) return s end return {newstack = newstack}