lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Aug 9, 2010, at 1:43 PM, Patrick Donnelly wrote:

> (One could use debug.upvaluejoin to give it a new upvalue,
> but this is an even worse hack in my opinion.)

Eh! Watch your language! :P

In any case, what about the good, old setfenv? 

Perhaps something along these lines, or something:

local debug = require( 'debug' )
local getinfo = debug.getinfo
local getupvalue = debug.getupvalue
local upvaluejoin = debug.upvaluejoin

local function GetFunction( aFunction, aLevel )
    return ( type( aFunction ) == 'function' and aFunction or getinfo( aFunction + aLevel, 'f' ).func )
end

local function UpValues( aFunction )
    local anIndex = 0
    
    return function()
        anIndex = anIndex + 1
        local aName, aValue = getupvalue( aFunction, anIndex ) 
        
        if aName then
            return anIndex, aName, aValue
        end
    end
end

function getfenv( aFunction )
    local aFunction = GetFunction( aFunction, 2 )

    for anIndex, aName, aValue in UpValues( aFunction ) do
        if aName == '_ENV' then
            return aValue
        end
    end

    error( 'No _ENV found for ' .. aFunction )
end

function setfenv( aFunction, anEnvironment )
    local aFunction = GetFunction( aFunction, 2 )

    for anIndex, aName, aValue in UpValues( aFunction ) do
        if aName == '_ENV' then
            return upvaluejoin( aFunction, anIndex, function() return anEnvironment end, 1 )
        end
    end

    error( 'No _ENV found for ' .. aFunction )
end