Fix debug.getlocal, debug.setlocal to match C lua logic.
This commit is contained in:
@@ -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 );
|
||||
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();
|
||||
vm.pushlvalue( name );
|
||||
if ( name != null ) {
|
||||
vm.pushlvalue(name);
|
||||
} else {
|
||||
vm.pushnil();
|
||||
}
|
||||
}
|
||||
|
||||
private CallInfo getcallinfo(LuaState vm, LuaState threadVm, int level) {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user