local register = {}
local registry = {
defercheck = function() return true end
-- used to warn about deferments that have not been discharged by a certain threshold
}
registry.mk = function(name,db)
local reg = {}
if not db then -- auxiliary db, stored in registry itself
reg.db = {}
db = reg.db
end
local dat = {
iters = {};
state = {};
defer = {};
}
reg.invoke = function(fnid,tgtid)
local fno = dat.iters[fnid]
if not fno then return false end
local runid = fnid .. '@' ..tgtid
if dat.state[runid] then return true end
if fno.deps then for k,f in pairs(fno.deps) do
if reg.invoke(f,tgtid) == false then return false end
end end
fno.fn(tgtid, db[tgtid])
dat.state[runid] = true
return true
end
reg.foreach = function(ident,deps,fn)
dat.iters[ident] = {deps = deps, fn = fn}
for k in pairs(db) do
if reg.invoke(ident,k) == false then
-- not all dependencies are available
-- to run yet; must defer until then
dat.defer[#dat.defer+1] = ident
return false
end
end
for i,dfn in pairs(dat.defer) do
local deferred = dat.iters[dfn]
for _,d in pairs(deferred.deps) do
if not dat.iters[d] then goto skipdfmt end
end
-- a deferred function can now be run, do so
table.remove(dat.defer,i)
reg.foreach(dfn,deferred.deps,deferred.fn)
::skipdfmt::end
return true
end
reg.link = function(key,value)
-- support simple arrays as well as kv stores
if value == nil then
value = key
key = #db+1
end
db[key] = value
for id in pairs(dat.iters) do
reg.invoke(id,key)
end
return value
end
reg.meld = function(tbl)
for k,v in pairs(tbl) do reg.link(k,v) end
end
register[name] = reg
local nextfn = registry.defercheck
registry.defercheck = function()
if #dat.defer ~= 0 then
print('WARNING: ' .. tostring(#dat.defer) .. ' deferred iterator(s) have not yet been discharged for registry “' .. name .. '”')
local log = print
for i,v in pairs(dat.defer) do
log('\t' .. tostring(i) .. ') ' .. v)
end
log('there is likely a missing dependency or dependency ordering problem. also make sure you have spelled the names of the iterator dependencies correctly')
return false
end
nextfn()
end
return reg
end
return registry
--[[
if sorcery.DEBUG then
local function dump(tbl,indent)
indent = indent or 0
local space = string.rep(' ',indent*4)
for k,v in pairs(tbl) do
if type(v) == 'table' then
print(string.format('%s%s = {',space,k))
dump(v,indent + 1)
print(string.format('%s}', space))
else
print(string.format('%s%s = %q',space,k,tostring(v)))
end
end
end
local metals = {
oregonium = {desc = 'Oregonium'};
nevadite = {desc = 'Nevadite'};
}
local myreg = sorcery.registry.mk('metals',metals)
sorcery.register.metals.link('californium', {
desc = "Californium";
})
sorcery.register.metals.foreach('sorcery:mkingot',{'sorcery:mkfrag'}, function(k,v)
local ingot = 'sorcery:' .. k .. '_ingot'
print('registered',ingot)
v.parts = v.parts or {}
v.parts.ingot = ingot;
end)
sorcery.registry.defercheck()
sorcery.register.metals.link('washingtonium', {
desc = "Washingtonium";
})
sorcery.register.metals.foreach('sorcery:mkfrag',{}, function(k,v)
local fragment = 'sorcery:' .. k .. '_fragment'
print('registered',fragment)
v.parts = v.parts or {}
v.parts.fragment = fragment;
end)
sorcery.register.metals.link('biloxite', {
desc = "Biloxite";
})
dump(metals)
if sorcery.registry.defercheck() then
print('lingering deferments!')
else
print('all good!')
end
end
]]