Intro
Hello Lua programmers.
I don't have much experience in Lua programming language, it is still a new thing for me.
I've run into a problem with coding a recursive function that is supposed to build 'function path' for each function in (any) given Lua table.
Example
I've the following Lua table:
_G["foo_lua_bar_libs"] = {
["my cool lib A"] = {
["add"] = function(a, b) return a + b end,
["sub"] = function(a, b) return a - b end,
["mul"] = function(a, b) return a * b end,
["div"] = function(a, b) return a / b end
},
["last?"] = function() return -1 end,
["my cool lib B"] = {
["B 1 hex"] = function() return 0xB1 end,
["B 2"] = function() return 0xB2 end,
["B utilib"] = {
["idk"] = function() return '1234567890' end,
["calc"] = function() return math.pi end,
["crash"] = function() print(string.rep(' ', math.huge)) end,
["first"] = function(x) return x or false end
},
["main"] = {
["phys"] = {
["calc"] = function(c, s) return math.cos(c) * math.sin(s) end
},
["internal"] = {
-- no function in here
},
[""] = function() local _ = "i am unnamed" end,
["foo . bar"] = {
["foo"] = "bar" .. 0,
--["bar"] = _G
},
["math"] = {
calc = function(x, y) return x * x + y * y end,
pi = math.pi, -- not a function
cos = math.cos,
[math.sin] = math.random
}
}
},
[""] = {
[false] = function() return true end,
[.80] = function(n) return 0.01 * n * n end,
["i am a function in nameless lib"] = function() return 1234 end,
i_am_totally_a_function = 'not a function',
["hi. i am a \"quoted!\" func."] = function() return "quoted", '!' end,
["\r\n"] = function() return "win" end
},
[ [[misc.lib]] ] = {
["..."] = function(...) return ... end,
nothing = function() return nil end,
["nil"] = nil, -- not a function
crash = function() while 0 do end end,
["end"] = function() end,
[string] = " a string; not a function "
}
}
I need a recursive Lua function (lets call it BuildFunctionPath
), which would build a function path for the given table, so that if I call BuildFunctionPath
function:
local libs_function_path = BuildFunctionPath(_G.foo_lua_bar_libs, nil, { "_G", "foo_lua_bar_libs" })
BuildFunctionPath
function would return the following table to the libs_function_path
variable:
{
["_G[\"foo_lua_bar_libs\"][\"last?\"]"] = function() return -1 end,
["_G[\"foo_lua_bar_libs\"][\"my cool lib A\"][\"add\"]"] = function(a, b) return a + b end,
["_G[\"foo_lua_bar_libs\"][\"my cool lib A\"][\"div\"]"] = function(a, b) return a / b end,
["_G[\"foo_lua_bar_libs\"][\"my cool lib A\"][\"mul\"]"] = function(a, b) return a * b end,
["_G[\"foo_lua_bar_libs\"][\"my cool lib A\"][\"sub\"]"] = function(a, b) return a - b end,
["_G[\"foo_lua_bar_libs\"][\"my cool lib B\"][\"B 1 hex\"]"] = function() return 0xB1 end,
["_G[\"foo_lua_bar_libs\"][\"my cool lib B\"][\"B 2\"]"] = function() return 0xB2 end,
["_G[\"foo_lua_bar_libs\"][\"my cool lib B\"][\"B utilib\"][\"calc\"]"] = function() return math.pi end,
["_G[\"foo_lua_bar_libs\"][\"my cool lib B\"][\"B utilib\"][\"crash\"]"] = function() print(string.rep(' ', math.huge)) end,
["_G[\"foo_lua_bar_libs\"][\"my cool lib B\"][\"B utilib\"][\"first\"]"] = function(x) return x or false end
["_G[\"foo_lua_bar_libs\"][\"my cool lib B\"][\"B utilib\"][\"idk\"]"] = function() return '1234567890' end,
["_G[\"foo_lua_bar_libs\"][\"my cool lib B\"][\"main\"][\"\"]"] = function() local _ = "i am unnamed" end,
["_G[\"foo_lua_bar_libs\"][\"my cool lib B\"][\"main\"][\"math\"][\"calc\"]"] = function(x, y) return x * x + y * y end,
["_G[\"foo_lua_bar_libs\"][\"my cool lib B\"][\"main\"][\"math\"][\"cos\"]"] = math.cos,
["_G[\"foo_lua_bar_libs\"][\"my cool lib B\"][\"main\"][\"math\"][math.sin]"] = math.random,
["_G[\"foo_lua_bar_libs\"][\"my cool lib B\"][\"main\"][\"phys\"][\"calc\"]"] = function(c, s) return math.cos(c) * math.sin(s) end,
["_G[\"foo_lua_bar_libs\"][\"\"][false]"] = function() return true end,
["_G[\"foo_lua_bar_libs\"][\"\"][0.80]"] = function(n) return 0.01 * n * n end,
["_G[\"foo_lua_bar_libs\"][\"\"][\"\\r\\n\"]"] = function() return "win" end,
["_G[\"foo_lua_bar_libs\"][\"\"][\"hi. i am a \\\"quoted!\\\" func.\"]"] = function() return "quoted", '!' end,
["_G[\"foo_lua_bar_libs\"][\"\"][\"i am a function in nameless lib\"]"] = function() return 1234 end,
["_G[\"foo_lua_bar_libs\"][\"misc.lib\"][\"...\"]"] = function(...) return ... end,
["_G[\"foo_lua_bar_libs\"][\"misc.lib\"][\"crash\"]"] = function() while 0 do end,
["_G[\"foo_lua_bar_libs\"][\"misc.lib\"][\"end\"]"] = function() end,
["_G[\"foo_lua_bar_libs\"][\"misc.lib\"][\"nothing\"]"] = function() return nil end
}
Here is the code I've got stuck at and I don't know how to finish the BuildFunctionPath
function:
function BuildFunctionPath(tbl, done, path)
-- Please help me with this function.
local functionStore = {} -- Final return table
if tbl == nil then tbl = _G end
if done == nil then done = {} end
if path == nil then path = { "_G" } end
for key, value in pairs(tbl) do
if type(value) == "table" and not done[value] then
done[value] = true
-- I am stuck...
local pathIndex = #path + 1
path[pathIndex] = key
--print(string.format("%q", path)) -- Quoted/Escaped path string
--BuildFunctionPath(value, done, path) -- Recursion....
path[pathIndex] = nil
done[value] = nil
elseif type(value) == "function" then
functionStore[path] = value
end
end
end
If you are wondering why I need such function, it is so that I can know exactly in which particular table a given function is stored in.
Take a look at this screenshot: https://i.stack.imgur.com/Rh7Wr.png
So, if user enters "_G[\"print\"]"
as path, it would return a _G.print
function. Also, by creating inverse table of (_G
) function path table, a user can then provide _G.print
function and it would return "_G[\"print\"]"
- the path string. Genius.
Please I need your help. Thanks for your time! :)
(Pardon my bad English.)