Improve compatibility with lua 5.2.

This commit is contained in:
James Roseborough
2012-09-21 14:32:07 +00:00
parent be4a320bf9
commit 0c93edfd56
6 changed files with 125 additions and 111 deletions

View File

@@ -340,5 +340,22 @@ public class Lua {
/* number of list items to accumulate before a SETLIST instruction */ /* number of list items to accumulate before a SETLIST instruction */
public static final int LFIELDS_PER_FLUSH = 50; public static final int LFIELDS_PER_FLUSH = 50;
private static final int MAXSRC = 80;
public static String chunkid( String source ) {
if ( source.startsWith("=") )
return source.substring(1);
String end = "";
if ( source.startsWith("@") ) {
source = source.substring(1);
} else {
source = "[string \""+source;
end = "\"]";
}
int n = source.length() + end.length();
if ( n > MAXSRC )
source = source.substring(0,MAXSRC-end.length()-3) + "...";
return source + end;
}
} }

View File

@@ -71,11 +71,18 @@ public class LuaFunction extends LuaValue {
} }
public String tojstring() { public String tojstring() {
String s = getClass().getName(); return "function: " + classnamestub();
return "function: " + s.substring(Math.max(s.lastIndexOf('.'),s.lastIndexOf('$'))+1);
} }
public LuaString strvalue() { public LuaString strvalue() {
return valueOf(tojstring()); return valueOf(tojstring());
} }
/** Return the last part of the class name, to be used as a function name in tojstring and elsewhere.
* @return String naming the last part of the class name after the last dot (.) or dollar sign ($).
*/
public String classnamestub() {
String s = getClass().getName();
return s.substring(Math.max(s.lastIndexOf('.'),s.lastIndexOf('$'))+1);
}
} }

View File

@@ -61,7 +61,6 @@ public class LexState {
} }
private static final int EOZ = (-1); private static final int EOZ = (-1);
private static final int MAXSRC = 80;
private static final int MAX_INT = Integer.MAX_VALUE-2; private static final int MAX_INT = Integer.MAX_VALUE-2;
private static final int UCHAR_MAX = 255; // TODO, convert to unicode CHAR_MAX? private static final int UCHAR_MAX = 255; // TODO, convert to unicode CHAR_MAX?
private static final int LUAI_MAXCCALLS = 200; private static final int LUAI_MAXCCALLS = 200;
@@ -260,29 +259,13 @@ public class LexState {
} }
void lexerror( String msg, int token ) { void lexerror( String msg, int token ) {
String cid = chunkid( source.tojstring() ); // TODO: get source name from source String cid = Lua.chunkid( source.tojstring() );
L.pushfstring( cid+":"+linenumber+": "+msg ); L.pushfstring( cid+":"+linenumber+": "+msg );
if ( token != 0 ) if ( token != 0 )
L.pushfstring( "syntax error: "+msg+" near "+txtToken(token) ); L.pushfstring( "syntax error: "+msg+" near "+txtToken(token) );
throw new LuaError(cid+":"+linenumber+": "+msg); throw new LuaError(cid+":"+linenumber+": "+msg);
} }
String chunkid( String source ) {
if ( source.startsWith("=") )
return source.substring(1);
String end = "";
if ( source.startsWith("@") ) {
source = source.substring(1);
} else {
source = "[string \""+source;
end = "\"]";
}
int n = source.length() + end.length();
if ( n > MAXSRC )
source = source.substring(0,MAXSRC-end.length()-3) + "...";
return source + end;
}
void syntaxerror( String msg ) { void syntaxerror( String msg ) {
lexerror( msg, t.token ); lexerror( msg, t.token );
} }

View File

@@ -37,6 +37,7 @@ import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Print; import org.luaj.vm2.Print;
import org.luaj.vm2.Prototype; import org.luaj.vm2.Prototype;
import org.luaj.vm2.Varargs; import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.DebugLib.CallFrame;
/** /**
* Subclass of {@link LibFunction} which implements the lua standard {@code debug} * Subclass of {@link LibFunction} which implements the lua standard {@code debug}
@@ -207,13 +208,13 @@ public class DebugLib extends OneArgFunction {
} }
if (what.indexOf('n') >= 0) { if (what.indexOf('n') >= 0) {
if (frame != null) { if (frame != null) {
LuaString[] kind = getfuncname(frame); DebugInfo ar = frame.getinfo("n");
info.set(NAME, kind!=null? kind[0]: QMARK); info.set(NAME, LuaValue.valueOf(ar.name));
info.set(NAMEWHAT, kind!=null? kind[1]: EMPTYSTRING); info.set(NAMEWHAT, LuaValue.valueOf(ar.namewhat));
} }
} }
if (what.indexOf('t') >= 0) { if (what.indexOf('t') >= 0) {
info.set(ISTAILCALL, frame != null && frame.istailcall()? ONE: ZERO); info.set(ISTAILCALL, ZERO);
} }
if (what.indexOf('L') >= 0) { if (what.indexOf('L') >= 0) {
LuaTable lines = new LuaTable(); LuaTable lines = new LuaTable();
@@ -505,6 +506,8 @@ public class DebugLib extends OneArgFunction {
for (int i = frame.length; i < n; ++i) for (int i = frame.length; i < n; ++i)
f[i] = new CallFrame(); f[i] = new CallFrame();
frame = f; frame = f;
for (int i = 1; i < n; ++i)
f[i].previous = f[i-1];
} }
return frame[calls++]; return frame[calls++];
} }
@@ -534,24 +537,30 @@ public class DebugLib extends OneArgFunction {
String traceback(int level) { String traceback(int level) {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append( "stack traceback:" ); sb.append( "stack traceback:" );
for (DebugLib.CallFrame c, prev = null; (c = getCallFrame(level++)) != null; prev = c ) { for (DebugLib.CallFrame c; (c = getCallFrame(level++)) != null; ) {
DebugInfo ar = c.getinfo("Slnt", prev);
prev = c;
sb.append("\n\t"); sb.append("\n\t");
sb.append( c.shortsource() ); sb.append( c.shortsource() );
sb.append( ':' ); sb.append( ':' );
if (c.currentline() > 0) if (c.currentline() > 0)
sb.append( c.currentline()+":" ); sb.append( c.currentline()+":" );
sb.append( " in " ); sb.append( " in " );
sb.append( c.tracename() ); DebugInfo ar = c.getinfo("n");
if (c.istailcall()) if (c.linedefined() == 0)
sb.append("\n\t(...tail calls...)"); sb.append("main chunk");
else if ( ar.name != null ) {
sb.append( "function '" );
sb.append( ar.name );
sb.append( '\'' );
} else {
sb.append( "function <"+c.shortsource()+":"+c.linedefined()+">" );
}
} }
sb.append("\n\t[Java]: in ?");
return sb.toString(); return sb.toString();
} }
DebugLib.CallFrame getCallFrame(int level) { DebugLib.CallFrame getCallFrame(int level) {
if (level < 1 || level >= calls) if (level < 1 || level > calls)
return null; return null;
return frame[calls-level]; return frame[calls-level];
} }
@@ -570,12 +579,11 @@ public class DebugLib extends OneArgFunction {
int top; int top;
Varargs v; Varargs v;
LuaValue[] stack; LuaValue[] stack;
boolean tail; CallFrame previous;
void set(LuaClosure function, Varargs varargs, LuaValue[] stack) { void set(LuaClosure function, Varargs varargs, LuaValue[] stack) {
this.f = function; this.f = function;
this.v = varargs; this.v = varargs;
this.stack = stack; this.stack = stack;
this.tail = false;
} }
public String shortsource() { public String shortsource() {
return f.isclosure()? DebugLib.shortsource(f.checkclosure().p): "[Java]"; return f.isclosure()? DebugLib.shortsource(f.checkclosure().p): "[Java]";
@@ -592,8 +600,6 @@ public class DebugLib extends OneArgFunction {
this.pc = pc; this.pc = pc;
this.v = v; this.v = v;
this.top = top; this.top = top;
if (f.checkclosure().p.code[pc] == Lua.OP_TAILCALL)
this.tail = true;
if (TRACE) if (TRACE)
Print.printState(f.checkclosure(), pc, stack, top, v); Print.printState(f.checkclosure(), pc, stack, top, v);
} }
@@ -620,20 +626,7 @@ public class DebugLib extends OneArgFunction {
} }
String sourceline() { String sourceline() {
if ( !f.isclosure() ) return f.tojstring(); if ( !f.isclosure() ) return f.tojstring();
String s = f.checkclosure().p.source.tojstring(); return DebugLib.shortsource(f.checkclosure().p) + ":" + currentline();
int line = currentline();
return (s.startsWith("@")||s.startsWith("=")? s.substring(1): s) + ":" + line;
}
String tracename() {
LuaString[] kind = getfuncname(this);
if (kind[0] == null)
return "function "+kind[1].tojstring();
// if (kind[0] == M)
// return "main chunk";
if (kind[0] == JAVA)
return "function "+kind[1].tojstring();
return "function <"+shortsource()+":"+linedefined()+">";
} }
private int linedefined() { private int linedefined() {
return f.isclosure()? f.checkclosure().p.linedefined: -1; return f.isclosure()? f.checkclosure().p.linedefined: -1;
@@ -642,14 +635,7 @@ public class DebugLib extends OneArgFunction {
if ( !f.isclosure() ) return null; if ( !f.isclosure() ) return null;
return f.checkclosure().p.getlocalname(index, pc); return f.checkclosure().p.getlocalname(index, pc);
} }
String tojstring() { DebugInfo getinfo(String what) {
return tracename()+" "+sourceline();
}
boolean istailcall() {
return tail;
}
DebugInfo getinfo(String what, CallFrame previous) {
DebugInfo ar = new DebugInfo(); DebugInfo ar = new DebugInfo();
for (int i = 0, n = what.length(); i < n; ++i) { for (int i = 0, n = what.length(); i < n; ++i) {
switch (what.charAt(i)) { switch (what.charAt(i)) {
@@ -660,13 +646,14 @@ public class DebugLib extends OneArgFunction {
ar.linedefined = p.linedefined; ar.linedefined = p.linedefined;
ar.lastlinedefined = p.lastlinedefined; ar.lastlinedefined = p.lastlinedefined;
ar.what = (ar.linedefined == 0) ? "main" : "Lua"; ar.what = (ar.linedefined == 0) ? "main" : "Lua";
ar.short_src = DebugLib.shortsource(p);
} else { } else {
ar.source = "=[Java]"; ar.source = "=[Java]";
ar.linedefined = -1; ar.linedefined = -1;
ar.lastlinedefined = -1; ar.lastlinedefined = -1;
ar.what = "Java"; ar.what = "Java";
ar.short_src = f.classnamestub();
} }
ar.short_src = chunkid(ar.source);
break; break;
case 'l': case 'l':
ar.currentline = currentline(); ar.currentline = currentline();
@@ -684,47 +671,33 @@ public class DebugLib extends OneArgFunction {
} }
break; break;
case 't': case 't':
ar.istailcall = this.tail; ar.istailcall = false;
break; break;
case 'n': { case 'n': {
/* calling function is a known Lua function? */ /* calling function is a known Lua function? */
if (!tail && (previous != null && previous.f.isclosure())) { if (previous != null && previous.f.isclosure()) {
LuaString[] kind = getfuncname(previous); NameWhat nw = getfuncname(previous);
ar.name = String.valueOf(kind[0]); if (nw != null) {
ar.namewhat = String.valueOf(kind[1]); ar.name = nw.name;
} ar.namewhat = nw.namewhat;
else }
ar.namewhat = null; }
if (ar.namewhat == null) { else
ar.namewhat = ""; /* not found */ ar.namewhat = null;
ar.name = null; if (ar.namewhat == null) {
} ar.namewhat = ""; /* not found */
break; ar.name = null;
}
break;
} }
default: default:
break; break;
} }
} }
return null; return ar;
} }
} }
static String chunkid( String source ) {
if ( source.startsWith("=") )
return source.substring(1);
String end = "";
if ( source.startsWith("@") ) {
source = source.substring(1);
} else {
source = "[string \""+source;
end = "\"]";
}
int n = source.length() + end.length();
if ( n > 50 )
source = source.substring(0,50-end.length()-3) + "...";
return source + end;
}
static LuaString findupvalue(LuaClosure c, int up) { static LuaString findupvalue(LuaClosure c, int up) {
if ( c.upValues != null && up > 0 && up <= c.upValues.length ) { if ( c.upValues != null && up > 0 && up <= c.upValues.length ) {
if ( c.p.upvalues != null && up <= c.p.upvalues.length ) if ( c.p.upvalues != null && up <= c.p.upvalues.length )
@@ -748,9 +721,19 @@ public class DebugLib extends OneArgFunction {
if (!x) throw new RuntimeException("lua_assert failed"); if (!x) throw new RuntimeException("lua_assert failed");
} }
public static LuaString[] getfuncname(DebugLib.CallFrame frame) { static class NameWhat {
final String name;
final String namewhat;
NameWhat(String name, String namewhat) {
this.name = name;
this.namewhat = namewhat;
}
}
// Return the name info if found, or null if no useful information could be found.
static NameWhat getfuncname(DebugLib.CallFrame frame) {
if (!frame.f.isclosure()) if (!frame.f.isclosure())
return new LuaString[] { frame.f.strvalue(), JAVA }; return new NameWhat(frame.f.classnamestub(), "Java");
Prototype p = frame.f.checkclosure().p; Prototype p = frame.f.checkclosure().p;
int pc = frame.pc; int pc = frame.pc;
int i = p.code[pc]; /* calling instruction */ int i = p.code[pc]; /* calling instruction */
@@ -760,7 +743,7 @@ public class DebugLib extends OneArgFunction {
case Lua.OP_TAILCALL: /* get function name */ case Lua.OP_TAILCALL: /* get function name */
return getobjname(p, pc, Lua.GETARG_A(i)); return getobjname(p, pc, Lua.GETARG_A(i));
case Lua.OP_TFORCALL: /* for iterator */ case Lua.OP_TFORCALL: /* for iterator */
return new LuaString[] { FOR_ITERATOR, FOR_ITERATOR}; return new NameWhat("(for iterator)", "(for iterator");
/* all other instructions can call only through metamethods */ /* all other instructions can call only through metamethods */
case Lua.OP_SELF: case Lua.OP_SELF:
case Lua.OP_GETTABUP: case Lua.OP_GETTABUP:
@@ -782,15 +765,15 @@ public class DebugLib extends OneArgFunction {
default: default:
return null; /* else no useful name can be found */ return null; /* else no useful name can be found */
} }
return new LuaString[] { tm, METAMETHOD }; return new NameWhat( tm.tojstring(), "metamethod" );
} }
// return StrValue[] { name, namewhat } if found, null if not // return NameWhat if found, null if not
public static LuaString[] getobjname(Prototype p, int lastpc, int reg) { public static NameWhat getobjname(Prototype p, int lastpc, int reg) {
int pc = lastpc; // currentpc(L, ci); int pc = lastpc; // currentpc(L, ci);
LuaString name = p.getlocalname(reg + 1, pc); LuaString name = p.getlocalname(reg + 1, pc);
if (name != null) /* is a local? */ if (name != null) /* is a local? */
return new LuaString[] { name, LOCAL }; return new NameWhat( name.tojstring(), "local" );
/* else try symbolic execution */ /* else try symbolic execution */
pc = findsetreg(p, lastpc, reg); pc = findsetreg(p, lastpc, reg);
@@ -812,12 +795,12 @@ public class DebugLib extends OneArgFunction {
? p.getlocalname(t + 1, pc) ? p.getlocalname(t + 1, pc)
: (t < p.upvalues.length ? p.upvalues[t].name : QMARK); : (t < p.upvalues.length ? p.upvalues[t].name : QMARK);
name = kname(p, k); name = kname(p, k);
return new LuaString[] { name, vn != null && vn.eq_b(ENV)? GLOBAL: FIELD }; return new NameWhat( name.tojstring(), vn != null && vn.eq_b(ENV)? "global": "field" );
} }
case Lua.OP_GETUPVAL: { case Lua.OP_GETUPVAL: {
int u = Lua.GETARG_B(i); /* upvalue index */ int u = Lua.GETARG_B(i); /* upvalue index */
name = u < p.upvalues.length ? p.upvalues[u].name : QMARK; name = u < p.upvalues.length ? p.upvalues[u].name : QMARK;
return new LuaString[] { name, UPVALUE }; return new NameWhat( name.tojstring(), "upvalue" );
} }
case Lua.OP_LOADK: case Lua.OP_LOADK:
case Lua.OP_LOADKX: { case Lua.OP_LOADKX: {
@@ -825,14 +808,14 @@ public class DebugLib extends OneArgFunction {
: Lua.GETARG_Ax(p.code[pc + 1]); : Lua.GETARG_Ax(p.code[pc + 1]);
if (p.k[b].isstring()) { if (p.k[b].isstring()) {
name = p.k[b].strvalue(); name = p.k[b].strvalue();
return new LuaString[] { name, CONSTANT }; return new NameWhat( name.tojstring(), "constant" );
} }
break; break;
} }
case Lua.OP_SELF: { case Lua.OP_SELF: {
int k = Lua.GETARG_C(i); /* key index */ int k = Lua.GETARG_C(i); /* key index */
name = kname(p, k); name = kname(p, k);
return new LuaString[] { name, METHOD }; return new NameWhat( name.tojstring(), "method" );
} }
default: default:
break; break;

View File

@@ -150,12 +150,6 @@ function test()
printinfo( 'debug.getinfo(2,"fL")', debug.getinfo(2, "fL") ) printinfo( 'debug.getinfo(2,"fL")', debug.getinfo(2, "fL") )
printinfo( 'debug.getinfo(10,"")', pcall( debug.getinfo, 10, "" ) ) printinfo( 'debug.getinfo(10,"")', pcall( debug.getinfo, 10, "" ) )
printinfo( 'debug.getinfo(-10,"")', pcall( debug.getinfo, -10, "" ) ) printinfo( 'debug.getinfo(-10,"")', pcall( debug.getinfo, -10, "" ) )
--[[
for i=1,3 do
printinfo( 'debug.traceback("msg")', debug.traceback('msg') )
printinfo( 'debug.traceback("another",'..i..')', debug.traceback('another',i) )
end
--]]
print( '---' ) print( '---' )
return x return x
end end
@@ -216,6 +210,36 @@ tryhooks("r")
tryhooks("l") tryhooks("l")
tryhooks("crl") tryhooks("crl")
print( '----- debug.traceback' )
function test()
function a(msg)
print((string.gsub(debug.traceback(msg), "%[Java]", "[C]")))
end
local function b(msg)
pcall(a,msg)
end
c = function(i)
if i <= 0 then b('hi') return end
return c(i-1)
end
d = setmetatable({},{__index=function(t,k) v = c(k) return v end})
local e = function()
return d[0]
end
local f = {
g = function()
e()
end
}
h = function()
f.g()
end
local i = h
i()
end
pcall(test)
print( '----- debug.upvalueid' ) print( '----- debug.upvalueid' )
local x,y = 100,200 local x,y = 100,200
function a(b,c) function a(b,c)

Binary file not shown.