Fix recursive tracking

This commit is contained in:
Gabriel Tofvesson 2024-10-14 12:59:37 +02:00
parent 5b11cb12f5
commit 053b59cf00

View File

@ -73,7 +73,7 @@ end
local RecursionSentinel = {}
function RecursionSentinel.make(table, index)
local obj = { table = table }
local obj = { table = table, index = index }
setmetatable(obj, RecursionSentinel)
return obj
end
@ -87,42 +87,38 @@ function RecursionSentinel.isKnown(knownTables, value)
end
function RecursionSentinel.getSentinel(knownTables, value)
local sentinel = knownTables[value]
if sentinel == nil then
sentinel = knownTables[value]
knownTables[#knownTables+1] = value
knownTables[value] = RecursionSentinel.make(value, #knownTables)
end
return sentinel
return knownTables[value] or RecursionSentinel.add(knownTables, value)
end
function RecursionSentinel.add(knownTables, value)
local sentinel = RecursionSentinel.make(value)
local sentinel = RecursionSentinel.make(value, #knownTables)
knownTables[value] = sentinel
return sentinel
end
function RecursionSentinel.pop(knownTables)
local value = knownTables[#knownTables]
knownTables[#knownTables] = nil
function RecursionSentinel.remove(knownTables, value)
local sentinel = knownTables[value]
if sentinel then
sentinel.index = nil
end
knownTables[value] = nil
end
local function cloneNonRecursive(value, sentinels)
if type(value) == "table" then
local sentinel = RecursionSentinel.getSentinel(sentinels, value)
if RecursionSentinel.isKnown(sentinels, value) then
return RecursionSentinel.getSentinel(sentinels, value)
return sentinel
end
local clone = {}
local sentinel = RecursionSentinel.add(sentinels, value)
for i,v in ipairs(value) do
clone[i] = cloneNonRecursive(v, sentinels)
end
for k,v in pairs(value) do
clone[cloneNonRecursive(k, sentinels)] = cloneNonRecursive(v, sentinels)
end
RecursionSentinel.pop(sentinels)
RecursionSentinel.remove(sentinels, sentinel.table)
sentinel.value = clone
return sentinel.value