[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: How to change the function behavior at run-time in luav5.1.4
- From: steve donovan <steve.j.donovan@...>
- Date: Thu, 28 Jan 2010 08:49:52 +0200
On Thu, Jan 28, 2010 at 4:09 AM, 刘小凡 <zhqqmao@gmail.com> wrote:
> The origin of the problem is due to the early days of the code often are
> difficult to detect low-level errors, such as spelling errors, simple logic
> error, many of these errors can be reflected only in the run-time. Therefore
> developers may need to restart the server to reload all the scripts, to
> restore its original state, this process is too cumbersome!
That is very clear, and as you say the problem is that dofile() does
not know about the detailed environment of the existing code. There
are often local variables involved, so simply using the environment of
the file (usually just _G, could be a module) won't do.
Here is a little test program where a function with local references
is recompiled successfully:
local x,y = 10,20
function test ()
return x+y
end
function getlocals (level)
local i = 1
local values,indices = {},{}
while true do
local name,val = debug.getlocal(level,i)
if not name then break end
values[name] = val
indices[name] = i
i = i + 1
end
return values,indices
end
function recompile (level,str)
local fn,err = loadstring(str)
if not fn then return nil,err end
local locals,locals_idx = getlocals(level)
local env = {}
local scope = getfenv(level)
setmetatable(env,{
__index = function(tab, key)
local val = locals[key]
if val then return val end
val = scope[key]
if val then return val end
end,
__newindex = function(tab, key, val)
if locals[key] then
debug.setlocal(3,locals_idx[key],val)
locals[key] = val
else
scope[key] = val
end
end
})
fn()
setfenv(test,env)
end
recompile (3,[[
function test ()
x = 30
glob = 'hello'
return x*y
end
]]
)
print(test(),x,glob)
getlocals() uses the debug API to find all the local variables, names,
values and indexes. We use this to create a special environment for
the function. Any variables in the function will be first looked up in
this locals table, then in the enclosing environment (which is just _G
in this case). If any locals are _assigned_, then the debug API is
used to actually modify the locals.
Very proof-of-concept, but it does show a way.
steve d.