Skip to content

Instantly share code, notes, and snippets.

@stevedonovan
Last active August 29, 2015 13:58
Show Gist options
  • Save stevedonovan/10259826 to your computer and use it in GitHub Desktop.
Save stevedonovan/10259826 to your computer and use it in GitHub Desktop.
Utility module to simplify initializing locals from tables or modules.
local debug = require 'debug'
-- from.lua
-- supports some useful shortcuts when creating locals from tables or modules
-- require 'from'
-- local sin,cos,tan = slots(3) from(math)
-- local import,printf = slots(2) from 'pl.utils'
-- local pretty,utils,xml = slots(3) from 'pl.*'
--
-- Uses the debug library, so it's not very fast - only use for top-level initialization!
local finfo = {}
local unpack = table.unpack or unpack
function slots (n)
local f = debug.getinfo(2,'f').func
if not finfo[f] then
finfo[f] = {first = 1}
end
finfo[f].nslots = n
local res = {}
for i = 1,n do res[i] = true end
return unpack(res)
end
local function requirex (mod,level)
local ok, res = pcall(require,mod)
if not ok then
error(res,level)
else
return res
end
end
function from (T)
local f = debug.getinfo(2).func
local fi = finfo[f]
local nslots,first = fi.nslots,fi.first
if type(T) == 'string' then -- we are given a module
local wild = T:match '(.+%.)%*$'
if not wild then
T = requirex (T,3)
else -- proxy table where indexing requires the submodule
T = setmetatable({},{ __index = function(t,mod)
return requirex(wild..mod,4)
end})
end
end
local slot = first
-- collect all the active locals
local locals, append = {}, table.insert
while true do
local loc,v = debug.getlocal(2,slot)
if not loc then break end
append(locals,loc)
slot = slot + 1
end
for i = #locals-nslots+1,#locals do
local idx = i+first-1
debug.setlocal(2,idx,T[locals[i]])
end
fi.first = #locals
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment