Add support for OP_LOADKX. #43

This commit is contained in:
Enyby
2019-06-30 22:18:19 +03:00
parent 5c5176727a
commit e6736857b6
5 changed files with 109 additions and 79 deletions

View File

@@ -23,10 +23,10 @@ package org.luaj.vm2;
/** /**
* Constants for lua limits and opcodes. * Constants for lua limits and opcodes.
* <p> * <p>
* This is a direct translation of C lua distribution header file constants * This is a direct translation of C lua distribution header file constants
* for bytecode creation and processing. * for bytecode creation and processing.
*/ */
public class Lua { public class Lua {
/** version is supplied by ant build task */ /** version is supplied by ant build task */
@@ -80,7 +80,6 @@ public class Lua {
public static final int POS_Bx = POS_C; public static final int POS_Bx = POS_C;
public static final int POS_Ax = POS_A; public static final int POS_Ax = POS_A;
public static final int MAX_OP = ((1<<SIZE_OP)-1); public static final int MAX_OP = ((1<<SIZE_OP)-1);
public static final int MAXARG_A = ((1<<SIZE_A)-1); public static final int MAXARG_A = ((1<<SIZE_A)-1);
public static final int MAXARG_B = ((1<<SIZE_B)-1); public static final int MAXARG_B = ((1<<SIZE_B)-1);
@@ -89,17 +88,18 @@ public class Lua {
public static final int MAXARG_sBx = (MAXARG_Bx>>1); /* `sBx' is signed */ public static final int MAXARG_sBx = (MAXARG_Bx>>1); /* `sBx' is signed */
public static final int MAXARG_Ax = ((1<<SIZE_Ax)-1); public static final int MAXARG_Ax = ((1<<SIZE_Ax)-1);
public static final int MASK_OP = ((1<<SIZE_OP)-1)<<POS_OP; public static final int MASK_OP = ((1<<SIZE_OP)-1)<<POS_OP;
public static final int MASK_A = ((1<<SIZE_A)-1)<<POS_A; public static final int MASK_A = ((1<<SIZE_A)-1)<<POS_A;
public static final int MASK_B = ((1<<SIZE_B)-1)<<POS_B; public static final int MASK_B = ((1<<SIZE_B)-1)<<POS_B;
public static final int MASK_C = ((1<<SIZE_C)-1)<<POS_C; public static final int MASK_C = ((1<<SIZE_C)-1)<<POS_C;
public static final int MASK_Bx = ((1<<SIZE_Bx)-1)<<POS_Bx; public static final int MASK_Bx = ((1<<SIZE_Bx)-1)<<POS_Bx;
public static final int MASK_Ax = ((1<<SIZE_Ax)-1)<<POS_Ax;
public static final int MASK_NOT_OP = ~MASK_OP; public static final int MASK_NOT_OP = ~MASK_OP;
public static final int MASK_NOT_A = ~MASK_A; public static final int MASK_NOT_A = ~MASK_A;
public static final int MASK_NOT_B = ~MASK_B; public static final int MASK_NOT_B = ~MASK_B;
public static final int MASK_NOT_C = ~MASK_C; public static final int MASK_NOT_C = ~MASK_C;
public static final int MASK_NOT_Bx = ~MASK_Bx; public static final int MASK_NOT_Bx = ~MASK_Bx;
/* /*
** the following macros help to manipulate instructions ** the following macros help to manipulate instructions
@@ -213,8 +213,8 @@ public class Lua {
public static final int OP_LT = 25; /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ public static final int OP_LT = 25; /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
public static final int OP_LE = 26; /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ public static final int OP_LE = 26; /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
public static final int OP_TEST = 27; /* A C if not (R(A) <=> C) then pc++ */ public static final int OP_TEST = 27; /* A C if not (R(A) <=> C) then pc++ */
public static final int OP_TESTSET = 28; /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ public static final int OP_TESTSET = 28; /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
public static final int OP_CALL = 29; /* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ public static final int OP_CALL = 29; /* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
public static final int OP_TAILCALL = 30; /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ public static final int OP_TAILCALL = 30; /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
@@ -225,7 +225,7 @@ public class Lua {
public static final int OP_FORPREP = 33; /* A sBx R(A)-=R(A+2); pc+=sBx */ public static final int OP_FORPREP = 33; /* A sBx R(A)-=R(A+2); pc+=sBx */
public static final int OP_TFORCALL = 34; /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */ public static final int OP_TFORCALL = 34; /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
public static final int OP_TFORLOOP = 35; /* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx } */ public static final int OP_TFORLOOP = 35; /* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx } */
public static final int OP_SETLIST = 36; /* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ public static final int OP_SETLIST = 36; /* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
public static final int OP_CLOSURE = 37; /* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ public static final int OP_CLOSURE = 37; /* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
@@ -237,11 +237,11 @@ public class Lua {
public static final int NUM_OPCODES = OP_EXTRAARG + 1; public static final int NUM_OPCODES = OP_EXTRAARG + 1;
/* pseudo-opcodes used in parsing only. */ /* pseudo-opcodes used in parsing only. */
public static final int OP_GT = 63; // > public static final int OP_GT = 63; // >
public static final int OP_GE = 62; // >= public static final int OP_GE = 62; // >=
public static final int OP_NEQ = 61; // ~= public static final int OP_NEQ = 61; // ~=
public static final int OP_AND = 60; // and public static final int OP_AND = 60; // and
public static final int OP_OR = 59; // or public static final int OP_OR = 59; // or
/*=========================================================================== /*===========================================================================
Notes: Notes:
@@ -271,7 +271,7 @@ public class Lua {
** bits 4-5: B arg mode ** bits 4-5: B arg mode
** bit 6: instruction set register A ** bit 6: instruction set register A
** bit 7: operator is a test ** bit 7: operator is a test
*/ */
public static final int OpArgN = 0; /* argument is not used */ public static final int OpArgN = 0; /* argument is not used */
public static final int OpArgU = 1; /* argument is used */ public static final int OpArgU = 1; /* argument is used */
@@ -353,7 +353,7 @@ public class Lua {
source = "[string \""+source; source = "[string \""+source;
end = "\"]"; end = "\"]";
} }
int n = source.length() + end.length(); int n = source.length() + end.length();
if ( n > MAXSRC ) if ( n > MAXSRC )
source = source.substring(0,MAXSRC-end.length()-3) + "..."; source = source.substring(0,MAXSRC-end.length()-3) + "...";
return source + end; return source + end;

View File

@@ -22,22 +22,22 @@
package org.luaj.vm2; package org.luaj.vm2;
/** /**
* Extension of {@link LuaFunction} which executes lua bytecode. * Extension of {@link LuaFunction} which executes lua bytecode.
* <p> * <p>
* A {@link LuaClosure} is a combination of a {@link Prototype} * A {@link LuaClosure} is a combination of a {@link Prototype}
* and a {@link LuaValue} to use as an environment for execution. * and a {@link LuaValue} to use as an environment for execution.
* Normally the {@link LuaValue} is a {@link Globals} in which case the environment * Normally the {@link LuaValue} is a {@link Globals} in which case the environment
* will contain standard lua libraries. * will contain standard lua libraries.
* *
* <p> * <p>
* There are three main ways {@link LuaClosure} instances are created: * There are three main ways {@link LuaClosure} instances are created:
* <ul> * <ul>
* <li>Construct an instance using {@link #LuaClosure(Prototype, LuaValue)}</li> * <li>Construct an instance using {@link #LuaClosure(Prototype, LuaValue)}</li>
* <li>Construct it indirectly by loading a chunk via {@link Globals#load(java.io.Reader, String)} * <li>Construct it indirectly by loading a chunk via {@link Globals#load(java.io.Reader, String)}
* <li>Execute the lua bytecode {@link Lua#OP_CLOSURE} as part of bytecode processing * <li>Execute the lua bytecode {@link Lua#OP_CLOSURE} as part of bytecode processing
* </ul> * </ul>
* <p> * <p>
* To construct it directly, the {@link Prototype} is typically created via a compiler such as * To construct it directly, the {@link Prototype} is typically created via a compiler such as
* {@link org.luaj.vm2.compiler.LuaC}: * {@link org.luaj.vm2.compiler.LuaC}:
* <pre> {@code * <pre> {@code
* String script = "print( 'hello, world' )"; * String script = "print( 'hello, world' )";
@@ -46,9 +46,9 @@ package org.luaj.vm2;
* LuaValue globals = JsePlatform.standardGlobals(); * LuaValue globals = JsePlatform.standardGlobals();
* LuaClosure f = new LuaClosure(p, globals); * LuaClosure f = new LuaClosure(p, globals);
* f.call(); * f.call();
* }</pre> * }</pre>
* <p> * <p>
* To construct it indirectly, the {@link Globals#load(java.io.Reader, String)} method may be used: * To construct it indirectly, the {@link Globals#load(java.io.Reader, String)} method may be used:
* <pre> {@code * <pre> {@code
* Globals globals = JsePlatform.standardGlobals(); * Globals globals = JsePlatform.standardGlobals();
* LuaFunction f = globals.load(new StringReader(script), "script"); * LuaFunction f = globals.load(new StringReader(script), "script");
@@ -56,11 +56,11 @@ package org.luaj.vm2;
* c.call(); * c.call();
* }</pre> * }</pre>
* <p> * <p>
* In this example, the "checkclosure()" may fail if direct lua-to-java-bytecode * In this example, the "checkclosure()" may fail if direct lua-to-java-bytecode
* compiling using LuaJC is installed, because no LuaClosure is created in that case * compiling using LuaJC is installed, because no LuaClosure is created in that case
* and the value returned is a {@link LuaFunction} but not a {@link LuaClosure}. * and the value returned is a {@link LuaFunction} but not a {@link LuaClosure}.
* <p> * <p>
* Since a {@link LuaClosure} is a {@link LuaFunction} which is a {@link LuaValue}, * Since a {@link LuaClosure} is a {@link LuaFunction} which is a {@link LuaValue},
* all the value operations can be used directly such as: * all the value operations can be used directly such as:
* <ul> * <ul>
* <li>{@link LuaValue#call()}</li> * <li>{@link LuaValue#call()}</li>
@@ -71,7 +71,7 @@ package org.luaj.vm2;
* <li>{@link LuaValue#method(String,LuaValue)}</li> * <li>{@link LuaValue#method(String,LuaValue)}</li>
* <li>{@link LuaValue#invokemethod(String)}</li> * <li>{@link LuaValue#invokemethod(String)}</li>
* <li>{@link LuaValue#invokemethod(String,Varargs)}</li> * <li>{@link LuaValue#invokemethod(String,Varargs)}</li>
* <li> ...</li> * <li> ...</li>
* </ul> * </ul>
* @see LuaValue * @see LuaValue
* @see LuaFunction * @see LuaFunction
@@ -92,13 +92,13 @@ public class LuaClosure extends LuaFunction {
/** Create a closure around a Prototype with a specific environment. /** Create a closure around a Prototype with a specific environment.
* If the prototype has upvalues, the environment will be written into the first upvalue. * If the prototype has upvalues, the environment will be written into the first upvalue.
* @param p the Prototype to construct this Closure for. * @param p the Prototype to construct this Closure for.
* @param env the environment to associate with the closure. * @param env the environment to associate with the closure.
*/ */
public LuaClosure(Prototype p, LuaValue env) { public LuaClosure(Prototype p, LuaValue env) {
this.p = p; this.p = p;
this.initupvalue1(env); this.initupvalue1(env);
globals = env instanceof Globals? (Globals) env: null; globals = env instanceof Globals? (Globals) env: null;
} }
public void initupvalue1(LuaValue env) { public void initupvalue1(LuaValue env) {
@@ -191,13 +191,13 @@ public class LuaClosure extends LuaFunction {
// allow for debug hooks // allow for debug hooks
if (globals != null && globals.debuglib != null) if (globals != null && globals.debuglib != null)
globals.debuglib.onCall( this, varargs, stack ); globals.debuglib.onCall( this, varargs, stack );
// process instructions // process instructions
try { try {
for (; true; ++pc) { for (; true; ++pc) {
if (globals != null && globals.debuglib != null) if (globals != null && globals.debuglib != null)
globals.debuglib.onInstruction( pc, v, top ); globals.debuglib.onInstruction( pc, v, top );
// pull out instruction // pull out instruction
i = code[pc]; i = code[pc];
@@ -214,6 +214,17 @@ public class LuaClosure extends LuaFunction {
stack[a] = k[i>>>14]; stack[a] = k[i>>>14];
continue; continue;
case Lua.OP_LOADKX:/* A R(A) := Kst(extra arg) */
++pc;
i = code[pc];
if ((i & 0x3f) != Lua.OP_EXTRAARG) {
int op = i & 0x3f;
throw new LuaError("OP_EXTRAARG expected after OP_LOADKX, got " +
(op < Print.OPNAMES.length - 1 ? Print.OPNAMES[op] : "UNKNOWN_OP_" + op));
}
stack[a] = k[i>>>6];
continue;
case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */ case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */
stack[a] = (i>>>23!=0)? LuaValue.TRUE: LuaValue.FALSE; stack[a] = (i>>>23!=0)? LuaValue.TRUE: LuaValue.FALSE;
if ((i&(0x1ff<<14)) != 0) if ((i&(0x1ff<<14)) != 0)
@@ -300,7 +311,7 @@ public class LuaClosure extends LuaFunction {
{ {
if ( c > b+1 ) { if ( c > b+1 ) {
Buffer sb = stack[c].buffer(); Buffer sb = stack[c].buffer();
while ( --c>=b ) while ( --c>=b )
sb.concatTo(stack[c]); sb.concatTo(stack[c]);
stack[a] = sb.value(); stack[a] = sb.value();
} else { } else {
@@ -321,31 +332,31 @@ public class LuaClosure extends LuaFunction {
continue; continue;
case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).eq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) ) if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).eq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
++pc; ++pc;
continue; continue;
case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lt_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) ) if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lt_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
++pc; ++pc;
continue; continue;
case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lteq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) ) if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lteq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
++pc; ++pc;
continue; continue;
case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */ case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */
if ( stack[a].toboolean() != ((i&(0x1ff<<14))!=0) ) if ( stack[a].toboolean() != ((i&(0x1ff<<14))!=0) )
++pc; ++pc;
continue; continue;
case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A):= R(B) else pc++ */ case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A):= R(B) else pc++ */
/* note: doc appears to be reversed */ /* note: doc appears to be reversed */
if ( (o=stack[i>>>23]).toboolean() != ((i&(0x1ff<<14))!=0) ) if ( (o=stack[i>>>23]).toboolean() != ((i&(0x1ff<<14))!=0) )
++pc; ++pc;
else else
stack[a] = o; // TODO: should be sBx? stack[a] = o; // TODO: should be sBx?
continue; continue;
case Lua.OP_CALL: /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */ case Lua.OP_CALL: /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */
@@ -363,9 +374,9 @@ public class LuaClosure extends LuaFunction {
default: default:
b = i>>>23; b = i>>>23;
c = (i>>14)&0x1ff; c = (i>>14)&0x1ff;
v = stack[a].invoke(b>0? v = stack[a].invoke(b>0?
varargsOf(stack, a+1, b-1): // exact arg count varargsOf(stack, a+1, b-1): // exact arg count
varargsOf(stack, a+1, top-v.narg()-(a+1), v)); // from prev top varargsOf(stack, a+1, top-v.narg()-(a+1), v)); // from prev top
if ( c > 0 ) { if ( c > 0 ) {
v.copyto(stack, a, c-1); v.copyto(stack, a, c-1);
v = NONE; v = NONE;
@@ -384,18 +395,18 @@ public class LuaClosure extends LuaFunction {
case (4<<Lua.POS_B): return new TailcallVarargs(stack[a], varargsOf(stack[a+1],stack[a+2],stack[a+3])); case (4<<Lua.POS_B): return new TailcallVarargs(stack[a], varargsOf(stack[a+1],stack[a+2],stack[a+3]));
default: default:
b = i>>>23; b = i>>>23;
v = b>0? v = b>0?
varargsOf(stack,a+1,b-1): // exact arg count varargsOf(stack,a+1,b-1): // exact arg count
varargsOf(stack, a+1, top-v.narg()-(a+1), v); // from prev top varargsOf(stack, a+1, top-v.narg()-(a+1), v); // from prev top
return new TailcallVarargs( stack[a], v ); return new TailcallVarargs( stack[a], v );
} }
case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */ case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */
b = i>>>23; b = i>>>23;
switch ( b ) { switch ( b ) {
case 0: return varargsOf(stack, a, top-v.narg()-a, v); case 0: return varargsOf(stack, a, top-v.narg()-a, v);
case 1: return NONE; case 1: return NONE;
case 2: return stack[a]; case 2: return stack[a];
default: default:
return varargsOf(stack, a, b-1); return varargsOf(stack, a, b-1);
} }
@@ -448,7 +459,7 @@ public class LuaClosure extends LuaFunction {
o = stack[a]; o = stack[a];
if ( (b=i>>>23) == 0 ) { if ( (b=i>>>23) == 0 ) {
b = top - a - 1; b = top - a - 1;
int m = b - v.narg(); int m = b - v.narg();
int j=1; int j=1;
for ( ;j<=m; j++ ) for ( ;j<=m; j++ )
o.set(offset+j, stack[a + j]); o.set(offset+j, stack[a + j]);
@@ -482,11 +493,11 @@ public class LuaClosure extends LuaFunction {
if ( b == 0 ) { if ( b == 0 ) {
top = a + (b = varargs.narg()); top = a + (b = varargs.narg());
v = varargs; v = varargs;
} else { } else {
for ( int j=1; j<b; ++j ) for ( int j=1; j<b; ++j )
stack[a+j-1] = varargs.arg(j); stack[a+j-1] = varargs.arg(j);
} }
continue; continue;
case Lua.OP_EXTRAARG: case Lua.OP_EXTRAARG:
throw new java.lang.IllegalArgumentException("Uexecutable opcode: OP_EXTRAARG"); throw new java.lang.IllegalArgumentException("Uexecutable opcode: OP_EXTRAARG");
@@ -515,7 +526,7 @@ public class LuaClosure extends LuaFunction {
/** /**
* Run the error hook if there is one * Run the error hook if there is one
* @param msg the message to use in error hook processing. * @param msg the message to use in error hook processing.
* */ * */
String errorHook(String msg, int level) { String errorHook(String msg, int level) {
if (globals == null ) return msg; if (globals == null ) return msg;
@@ -536,7 +547,7 @@ public class LuaClosure extends LuaFunction {
} }
private void processErrorHooks(LuaError le, Prototype p, int pc) { private void processErrorHooks(LuaError le, Prototype p, int pc) {
le.fileline = (p.source != null? p.source.tojstring(): "?") + ":" le.fileline = (p.source != null? p.source.tojstring(): "?") + ":"
+ (p.lineinfo != null && pc >= 0 && pc < p.lineinfo.length? String.valueOf(p.lineinfo[pc]): "?"); + (p.lineinfo != null && pc >= 0 && pc < p.lineinfo.length? String.valueOf(p.lineinfo[pc]): "?");
le.traceback = errorHook(le.getMessage(), le.level); le.traceback = errorHook(le.getMessage(), le.level);
} }

View File

@@ -46,20 +46,20 @@ public class Constants extends Lua {
/* OpMode - basic instruction format */ /* OpMode - basic instruction format */
static final int static final int
iABC = 0, iABC = 0,
iABx = 1, iABx = 1,
iAsBx = 2; iAsBx = 2;
/* OpArgMask */ /* OpArgMask */
static final int static final int
OpArgN = 0, /* argument is not used */ OpArgN = 0, /* argument is not used */
OpArgU = 1, /* argument is used */ OpArgU = 1, /* argument is used */
OpArgR = 2, /* argument is a register or a jump offset */ OpArgR = 2, /* argument is a register or a jump offset */
OpArgK = 3; /* argument is a constant or register/constant */ OpArgK = 3; /* argument is a constant or register/constant */
protected static void _assert(boolean b) { protected static void _assert(boolean b) {
if (!b) if (!b)
throw new LuaError("compiler assert failed"); throw new LuaError("compiler assert failed");
} }
@@ -104,6 +104,11 @@ public class Constants extends Lua {
((a << POS_A) & MASK_A) | ((a << POS_A) & MASK_A) |
((bc << POS_Bx) & MASK_Bx) ; ((bc << POS_Bx) & MASK_Bx) ;
} }
static int CREATE_Ax(int o, int a) {
return ((o << POS_OP) & MASK_OP) |
((a << POS_Ax) & MASK_Ax) ;
}
// vector reallocation // vector reallocation
@@ -150,7 +155,7 @@ public class Constants extends Lua {
} }
static LexState.Labeldesc[] grow(LexState.Labeldesc[] v, int min_n) { static LexState.Labeldesc[] grow(LexState.Labeldesc[] v, int min_n) {
return v == null ? new LexState.Labeldesc[2] : v.length < min_n ? realloc(v, v.length*2) : v; return v == null ? new LexState.Labeldesc[2] : v.length < min_n ? realloc(v, v.length*2) : v;
} }
static LexState.Labeldesc[] realloc(LexState.Labeldesc[] v, int n) { static LexState.Labeldesc[] realloc(LexState.Labeldesc[] v, int n) {

View File

@@ -580,11 +580,11 @@ public class FuncState extends Constants {
break; break;
} }
case LexState.VK: { case LexState.VK: {
this.codeABx(OP_LOADK, reg, e.u.info); this.codeK(reg, e.u.info);
break; break;
} }
case LexState.VKNUM: { case LexState.VKNUM: {
this.codeABx(OP_LOADK, reg, this.numberK(e.u.nval())); this.codeK(reg, this.numberK(e.u.nval()));
break; break;
} }
case LexState.VRELOCABLE: { case LexState.VRELOCABLE: {
@@ -1116,6 +1116,20 @@ public class FuncState extends Constants {
return this.code(CREATE_ABx(o, a, bc), this.ls.lastline); return this.code(CREATE_ABx(o, a, bc), this.ls.lastline);
} }
int codeextraarg(int a) {
_assert(a <= MAXARG_Ax);
return this.code(CREATE_Ax(OP_EXTRAARG, a), this.ls.lastline);
}
int codeK(int reg, int k) {
if (k <= MAXARG_Bx)
return codeABx(OP_LOADK, reg, k);
else {
int p = codeABx(OP_LOADKX, reg, 0);
codeextraarg(k);
return p;
}
}
void setlist(int base, int nelems, int tostore) { void setlist(int base, int nelems, int tostore) {
int c = (nelems - 1) / LFIELDS_PER_FLUSH + 1; int c = (nelems - 1) / LFIELDS_PER_FLUSH + 1;

View File

@@ -62,14 +62,14 @@ public class LexState extends Constants {
private static final int EOZ = (-1); private static final int EOZ = (-1);
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;
private static final String LUA_QS(String s) { return "'"+s+"'"; } private static final String LUA_QS(String s) { return "'"+s+"'"; }
private static final String LUA_QL(Object o) { return LUA_QS(String.valueOf(o)); } private static final String LUA_QL(Object o) { return LUA_QS(String.valueOf(o)); }
private static final int LUA_COMPAT_LSTR = 1; // 1 for compatibility, 2 for old behavior private static final int LUA_COMPAT_LSTR = 1; // 1 for compatibility, 2 for old behavior
private static final boolean LUA_COMPAT_VARARG = true; private static final boolean LUA_COMPAT_VARARG = true;
public static boolean isReservedKeyword(String varName) { public static boolean isReservedKeyword(String varName) {
return RESERVED_LOCAL_VAR_KEYWORDS_TABLE.containsKey(varName); return RESERVED_LOCAL_VAR_KEYWORDS_TABLE.containsKey(varName);
@@ -84,7 +84,7 @@ public class LexState extends Constants {
/* /*
** grep "ORDER OPR" if you change these enums ** grep "ORDER OPR" if you change these enums
*/ */
static final int static final int
OPR_ADD=0, OPR_SUB=1, OPR_MUL=2, OPR_DIV=3, OPR_MOD=4, OPR_POW=5, OPR_ADD=0, OPR_SUB=1, OPR_MUL=2, OPR_DIV=3, OPR_MOD=4, OPR_POW=5,
OPR_CONCAT=6, OPR_CONCAT=6,
OPR_NE=7, OPR_EQ=8, OPR_NE=7, OPR_EQ=8,
@@ -92,11 +92,11 @@ public class LexState extends Constants {
OPR_AND=13, OPR_OR=14, OPR_AND=13, OPR_OR=14,
OPR_NOBINOPR=15; OPR_NOBINOPR=15;
static final int static final int
OPR_MINUS=0, OPR_NOT=1, OPR_LEN=2, OPR_NOUNOPR=3; OPR_MINUS=0, OPR_NOT=1, OPR_LEN=2, OPR_NOUNOPR=3;
/* exp kind */ /* exp kind */
static final int static final int
VVOID = 0, /* no value */ VVOID = 0, /* no value */
VNIL = 1, VNIL = 1,
VTRUE = 2, VTRUE = 2,
@@ -153,14 +153,14 @@ public class LexState extends Constants {
"::", "<eos>", "<number>", "<name>", "<string>", "<eof>", "::", "<eos>", "<number>", "<name>", "<string>", "<eof>",
}; };
final static int final static int
/* terminal symbols denoted by reserved words */ /* terminal symbols denoted by reserved words */
TK_AND=257, TK_BREAK=258, TK_DO=259, TK_ELSE=260, TK_ELSEIF=261, TK_AND=257, TK_BREAK=258, TK_DO=259, TK_ELSE=260, TK_ELSEIF=261,
TK_END=262, TK_FALSE=263, TK_FOR=264, TK_FUNCTION=265, TK_GOTO=266, TK_IF=267, TK_END=262, TK_FALSE=263, TK_FOR=264, TK_FUNCTION=265, TK_GOTO=266, TK_IF=267,
TK_IN=268, TK_LOCAL=269, TK_NIL=270, TK_NOT=271, TK_OR=272, TK_REPEAT=273, TK_IN=268, TK_LOCAL=269, TK_NIL=270, TK_NOT=271, TK_OR=272, TK_REPEAT=273,
TK_RETURN=274, TK_THEN=275, TK_TRUE=276, TK_UNTIL=277, TK_WHILE=278, TK_RETURN=274, TK_THEN=275, TK_TRUE=276, TK_UNTIL=277, TK_WHILE=278,
/* other terminal symbols */ /* other terminal symbols */
TK_CONCAT=279, TK_DOTS=280, TK_EQ=281, TK_GE=282, TK_LE=283, TK_NE=284, TK_CONCAT=279, TK_DOTS=280, TK_EQ=281, TK_GE=282, TK_LE=283, TK_NE=284,
TK_DBCOLON=285, TK_EOS=286, TK_NUMBER=287, TK_NAME=288, TK_STRING=289; TK_DBCOLON=285, TK_EOS=286, TK_NUMBER=287, TK_NAME=288, TK_STRING=289;
final static int FIRST_RESERVED = TK_AND; final static int FIRST_RESERVED = TK_AND;
@@ -175,7 +175,7 @@ public class LexState extends Constants {
} }
private boolean isalnum(int c) { private boolean isalnum(int c) {
return (c >= '0' && c <= '9') return (c >= '0' && c <= '9')
|| (c >= 'a' && c <= 'z') || (c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z') || (c >= 'A' && c <= 'Z')
|| (c == '_'); || (c == '_');
@@ -188,13 +188,13 @@ public class LexState extends Constants {
} }
private boolean isdigit(int c) { private boolean isdigit(int c) {
return (c >= '0' && c <= '9'); return (c >= '0' && c <= '9');
} }
private boolean isxdigit(int c) { private boolean isxdigit(int c) {
return (c >= '0' && c <= '9') return (c >= '0' && c <= '9')
|| (c >= 'a' && c <= 'f') || (c >= 'a' && c <= 'f')
|| (c >= 'A' && c <= 'F'); || (c >= 'A' && c <= 'F');
} }
private boolean isspace(int c) { private boolean isspace(int c) {
@@ -235,7 +235,7 @@ public class LexState extends Constants {
String token2str( int token ) { String token2str( int token ) {
if ( token < FIRST_RESERVED ) { if ( token < FIRST_RESERVED ) {
return iscntrl(token)? return iscntrl(token)?
L.pushfstring( "char("+((int)token)+")" ): L.pushfstring( "char("+((int)token)+")" ):
L.pushfstring( String.valueOf( (char) token ) ); L.pushfstring( String.valueOf( (char) token ) );
} else { } else {
@@ -821,7 +821,7 @@ public class LexState extends Constants {
/* dynamic structures used by the parser */ /* dynamic structures used by the parser */
static class Dyndata { static class Dyndata {
Vardesc[] actvar; /* list of active local variables */ Vardesc[] actvar; /* list of active local variables */
int n_actvar = 0; int n_actvar = 0;
Labeldesc[] gt; /* list of pending gotos */ Labeldesc[] gt; /* list of pending gotos */
int n_gt = 0; int n_gt = 0;
@@ -1610,7 +1610,7 @@ public class LexState extends Constants {
switch (t.token) { switch (t.token) {
case TK_ELSE: case TK_ELSEIF: case TK_END: case TK_EOS: case TK_ELSE: case TK_ELSEIF: case TK_END: case TK_EOS:
return true; return true;
case TK_UNTIL: case TK_UNTIL:
return withuntil; return withuntil;
default: return false; default: return false;
} }
@@ -1634,7 +1634,7 @@ public class LexState extends Constants {
static class LHS_assign { static class LHS_assign {
LHS_assign prev; LHS_assign prev;
/* variable (global, local, upvalue, or indexed) */ /* variable (global, local, upvalue, or indexed) */
expdesc v = new expdesc(); expdesc v = new expdesc();
}; };
@@ -1845,7 +1845,7 @@ public class LexState extends Constants {
if (this.testnext(',')) if (this.testnext(','))
this.exp1(); /* optional step */ this.exp1(); /* optional step */
else { /* default step = 1 */ else { /* default step = 1 */
fs.codeABx(Lua.OP_LOADK, fs.freereg, fs.numberK(LuaInteger.valueOf(1))); fs.codeK(fs.freereg, fs.numberK(LuaInteger.valueOf(1)));
fs.reserveregs(1); fs.reserveregs(1);
} }
this.forbody(base, line, 1, true); this.forbody(base, line, 1, true);