Modul:table/indexIpairs
Napohlad
- This module lacks a documentation subpage. Please create it.
- Useful links: root page • root page’s subpages • links • transclusions • testcases • sandbox
local table_get_unprotected_metatable = "Module:table/getUnprotectedMetatable"
local error = error
local ipairs = ipairs
local ipairs_iter = ipairs{}
local pcall = pcall
local rawget = rawget
local type = type
local function get_unprotected_metatable(...)
get_unprotected_metatable = require(table_get_unprotected_metatable)
return get_unprotected_metatable(...)
end
local current = {}
-- Iterator used when there is no __ipairs metamethod to deal with.
local function default_iter(t, i)
i = i + 1
local v = t[i]
if v ~= nil then
return i, v
end
end
local function index_ipairs(t)
if current[t] then
return ipairs_iter, t, 0
end
local mt = get_unprotected_metatable(t)
if mt == nil then
return ipairs_iter, t, 0
elseif not mt then
current[t] = true
-- Use pcall(), so that `t` can always be unset from `current`.
local success, iter, state, init = pcall(ipairs, t)
current[t] = nil
-- If there was an error, raise it.
if not success then
error(iter)
end
return iter, state, init
end
-- Iterate up through __index metamethods.
local parent
repeat
-- If an __ipairs metamethod is found, use the custom iterator.
local ipairs_mm = rawget(mt, "__ipairs")
if not (ipairs_mm == nil or ipairs_mm == index_ipairs) then
break
end
-- If __index isn't a table, use default_iter().
parent = rawget(mt, "__index")
if not (parent and type(parent) == "table") then
return default_iter, t, 0
end
-- If there's no metatable, use default_iter().
mt = get_unprotected_metatable(parent)
if mt == nil then
return default_iter, t, 0
end
-- get_unprotected_metatable() will return false if the metatable is
-- protected, which means there could be an __ipairs metamethod, so use the
-- custom iterator.
until not mt
local iter, state
return function(t, i)
local new_i = i + 1
local v = t[new_i]
if v ~= nil then
return new_i, v
-- Use iter() as a fallback.
elseif iter == nil then
iter, state = ipairs(parent)
end
return iter(state, i)
end, t, 0
end
return index_ipairs