Fix debug.getlocal, debug.setlocal to match C lua logic.

This commit is contained in:
James Roseborough
2009-03-25 18:28:30 +00:00
parent 4bdd4a6ea2
commit 1aa3a7561f
2 changed files with 69 additions and 27 deletions

View File

@@ -27,6 +27,7 @@ import org.luaj.vm.LClosure;
import org.luaj.vm.LFunction;
import org.luaj.vm.LInteger;
import org.luaj.vm.LNil;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LString;
import org.luaj.vm.LTable;
import org.luaj.vm.LValue;
@@ -69,6 +70,8 @@ public class DebugLib extends LFunction {
private static final int SETUPVALUE = 13;
private static final int TRACEBACK = 14;
private static final LString TEMPORARY = new LString("(*temporary)");
public static void install( LuaState vm ) {
LTable debug = new LTable();
for (int i = 1; i < NAMES.length; i++)
@@ -259,6 +262,43 @@ public class DebugLib extends LFunction {
}
}
private LString getlocalname (LPrototype f, int local_number, int pc) {
int i;
for (i = 0; i<f.locvars.length && f.locvars[i].startpc <= pc; i++) {
if (pc < f.locvars[i].endpc) { /* is variable active? */
local_number--;
if (local_number == 0)
return f.locvars[i].varname;
}
}
return null; /* not found */
}
private LString findlocal(LuaState vm, int cc, int n) {
CallInfo ci = vm.calls[cc];
LString name;
LPrototype fp = ci.closure.p;
if ( fp!=null && (name = getlocalname(fp, n, ci.pc-1)) != null)
return name;
return null;
}
/** pushes the value onto the stack, returns the name or null */
private LString getlocal(LuaState vm, int cc, int n) {
LString name = findlocal(vm, cc, n);
if ( name != null )
vm.pushlvalue( vm.stack[vm.calls[cc].base+(n-1)] );
return name;
}
/** pops the value onto the stack, sets it to the local, return name or null */
private LString setlocal(LuaState vm, int cc, int n) {
LString name = findlocal(vm, cc, n);
if ( name != null )
vm.stack[vm.calls[cc].base+(n-1)] = vm.poplvalue();
return name;
}
private void getlocal(LuaState vm) {
LuaState threadVm = vm;
if ( vm.gettop() >= 4 ) {
@@ -267,18 +307,16 @@ public class DebugLib extends LFunction {
}
int level = vm.checkint(2);
int local = vm.checkint(3);
CallInfo ci = getcallinfo(vm, threadVm, level);
LValue value = LNil.NIL;
LValue name = LNil.NIL;
LocVars[] vars = ci.closure.p.locvars;
if ( local > 0 && local <= ci.top-ci.base ) {
value = threadVm.stack[ ci.base + local - 1 ];
if ( vars != null && local > 0 && local <= vars.length )
name = vars[local-1].varname;
}
LString name = getlocal(threadVm, threadVm.cc-(level-1), local);
if ( name != null ) {
LValue value = vm.poplvalue();
vm.resettop();
vm.pushlvalue(name);
vm.pushlvalue(value);
} else {
vm.resettop();
vm.pushnil();
}
}
private void setlocal(LuaState vm) {
@@ -289,17 +327,14 @@ public class DebugLib extends LFunction {
}
int level = vm.checkint(2);
int local = vm.checkint(3);
LValue value = vm.topointer(4);
CallInfo ci = getcallinfo(vm, threadVm, level);
LValue name = LNil.NIL;
LocVars[] vars = ci.closure.p.locvars;
if ( local > 0 && local <= ci.top-ci.base ) {
threadVm.stack[ ci.base + local - 1 ] = value;
if ( vars != null && local > 0 && local <= vars.length )
name = vars[local-1].varname;
}
vm.settop(4);
LString name = setlocal(threadVm, threadVm.cc-(level-1), local);
vm.resettop();
if ( name != null ) {
vm.pushlvalue(name);
} else {
vm.pushnil();
}
}
private CallInfo getcallinfo(LuaState vm, LuaState threadVm, int level) {

View File

@@ -2,8 +2,8 @@
local print,tostring,_G = print,tostring,_G
local e,f,g,h,s
print( 'has debug', debug~=nil )
if not debug then error( 'no debug' ) end
-- debug.getfenv, debug.setfenv
print( '----- debug.getfenv, debug.setfenv' )
f = function(a)
return 'f:'..tostring(a)..'|'..tostring(b)
@@ -19,11 +19,13 @@ print( s, type(e), type(g), (e==G), pcall( f, 'abc' ) )
print( '----- debug.getlocal, debug.setlocal' )
h = function(v,i,n)
s = 'h-'..v..'-'..i
local x = debug.getlocal(v,i)
local y = debug.setlocal(v,i,n)
local x1,y1 = debug.getlocal(v,i)
local x2,y2 = debug.setlocal(v,i,n)
local x3,y3 = debug.getlocal(v,i)
return s..' -> '..v..'-'..i..' '..
'old='..tostring(x)..'('..tostring(y)..')'..' '..
'new='..tostring(n)
'get='..tostring(x1)..','..tostring(y1)..' '..
'set='..tostring(x2)..','..tostring(y2)..' '..
'get='..tostring(x3)..','..tostring(y3)..' '
end
g = function(...)
local p,q,r=7,8,9
@@ -36,7 +38,12 @@ f = function(a,b,c)
local t = g(a,b,c)
return t..'\tf locals='..','..a..','..b..','..c..','..d..','..e..','..f
end
for lvl=1,3 do
do lvl=1,1
for lcl=3,7 do
print( pcall( f, lvl, lcl, '#' ) )
end
end
do lvl=2,3
for lcl=0,7 do
print( pcall( f, lvl, lcl, '#' ) )
end