diff --git a/src/core/org/luaj/vm2/Lua.java b/src/core/org/luaj/vm2/Lua.java
index 9b9b0ce1..48452fe5 100644
--- a/src/core/org/luaj/vm2/Lua.java
+++ b/src/core/org/luaj/vm2/Lua.java
@@ -23,10 +23,10 @@ package org.luaj.vm2;
/**
- * Constants for lua limits and opcodes.
+ * Constants for lua limits and opcodes.
*
* 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 {
/** 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_Ax = POS_A;
-
public static final int MAX_OP = ((1<>1); /* `sBx' is signed */
public static final int MAXARG_Ax = ((1< 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_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_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)) */
@@ -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_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_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;
/* 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_NEQ = 61; // ~=
- public static final int OP_AND = 60; // and
- public static final int OP_OR = 59; // or
+ public static final int OP_NEQ = 61; // ~=
+ public static final int OP_AND = 60; // and
+ public static final int OP_OR = 59; // or
/*===========================================================================
Notes:
@@ -271,7 +271,7 @@ public class Lua {
** bits 4-5: B arg mode
** bit 6: instruction set register A
** bit 7: operator is a test
- */
+ */
public static final int OpArgN = 0; /* argument is not used */
public static final int OpArgU = 1; /* argument is used */
@@ -353,7 +353,7 @@ public class Lua {
source = "[string \""+source;
end = "\"]";
}
- int n = source.length() + end.length();
+ int n = source.length() + end.length();
if ( n > MAXSRC )
source = source.substring(0,MAXSRC-end.length()-3) + "...";
return source + end;
diff --git a/src/core/org/luaj/vm2/LuaClosure.java b/src/core/org/luaj/vm2/LuaClosure.java
index 76534c15..8aae7eea 100644
--- a/src/core/org/luaj/vm2/LuaClosure.java
+++ b/src/core/org/luaj/vm2/LuaClosure.java
@@ -22,22 +22,22 @@
package org.luaj.vm2;
/**
- * Extension of {@link LuaFunction} which executes lua bytecode.
+ * Extension of {@link LuaFunction} which executes lua bytecode.
*
- * 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.
* Normally the {@link LuaValue} is a {@link Globals} in which case the environment
- * will contain standard lua libraries.
+ * will contain standard lua libraries.
*
*
* There are three main ways {@link LuaClosure} instances are created:
- *
+ *
* - Construct an instance using {@link #LuaClosure(Prototype, LuaValue)}
* - Construct it indirectly by loading a chunk via {@link Globals#load(java.io.Reader, String)}
*
- Execute the lua bytecode {@link Lua#OP_CLOSURE} as part of bytecode processing
*
*
- * 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}:
*
{@code
* String script = "print( 'hello, world' )";
@@ -46,9 +46,9 @@ package org.luaj.vm2;
* LuaValue globals = JsePlatform.standardGlobals();
* LuaClosure f = new LuaClosure(p, globals);
* f.call();
- * }
+ * }
*
- * 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:
*
{@code
* Globals globals = JsePlatform.standardGlobals();
* LuaFunction f = globals.load(new StringReader(script), "script");
@@ -56,11 +56,11 @@ package org.luaj.vm2;
* c.call();
* }
*
- * 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
* and the value returned is a {@link LuaFunction} but not a {@link LuaClosure}.
- *
- * 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:
*
* - {@link LuaValue#call()}
@@ -71,7 +71,7 @@ package org.luaj.vm2;
* - {@link LuaValue#method(String,LuaValue)}
* - {@link LuaValue#invokemethod(String)}
* - {@link LuaValue#invokemethod(String,Varargs)}
- * - ...
+ * - ...
*
* @see LuaValue
* @see LuaFunction
@@ -92,13 +92,13 @@ public class LuaClosure extends LuaFunction {
/** Create a closure around a Prototype with a specific environment.
* 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.
*/
public LuaClosure(Prototype p, LuaValue env) {
this.p = p;
this.initupvalue1(env);
- globals = env instanceof Globals? (Globals) env: null;
+ globals = env instanceof Globals? (Globals) env: null;
}
public void initupvalue1(LuaValue env) {
@@ -191,13 +191,13 @@ public class LuaClosure extends LuaFunction {
// allow for debug hooks
if (globals != null && globals.debuglib != null)
- globals.debuglib.onCall( this, varargs, stack );
+ globals.debuglib.onCall( this, varargs, stack );
// process instructions
try {
for (; true; ++pc) {
if (globals != null && globals.debuglib != null)
- globals.debuglib.onInstruction( pc, v, top );
+ globals.debuglib.onInstruction( pc, v, top );
// pull out instruction
i = code[pc];
@@ -214,6 +214,17 @@ public class LuaClosure extends LuaFunction {
stack[a] = k[i>>>14];
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++ */
stack[a] = (i>>>23!=0)? LuaValue.TRUE: LuaValue.FALSE;
if ((i&(0x1ff<<14)) != 0)
@@ -300,7 +311,7 @@ public class LuaClosure extends LuaFunction {
{
if ( c > b+1 ) {
Buffer sb = stack[c].buffer();
- while ( --c>=b )
+ while ( --c>=b )
sb.concatTo(stack[c]);
stack[a] = sb.value();
} else {
@@ -321,31 +332,31 @@ public class LuaClosure extends LuaFunction {
continue;
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;
continue;
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;
continue;
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;
continue;
- case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */
- if ( stack[a].toboolean() != ((i&(0x1ff<<14))!=0) )
+ case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */
+ if ( stack[a].toboolean() != ((i&(0x1ff<<14))!=0) )
++pc;
continue;
case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A):= R(B) else pc++ */
/* 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;
else
- stack[a] = o; // TODO: should be sBx?
+ stack[a] = o; // TODO: should be sBx?
continue;
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:
b = i>>>23;
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, 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 ) {
v.copyto(stack, a, c-1);
v = NONE;
@@ -384,18 +395,18 @@ public class LuaClosure extends LuaFunction {
case (4<>>23;
- v = b>0?
+ v = b>0?
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 );
}
case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */
b = i>>>23;
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 2: return stack[a];
+ case 2: return stack[a];
default:
return varargsOf(stack, a, b-1);
}
@@ -448,7 +459,7 @@ public class LuaClosure extends LuaFunction {
o = stack[a];
if ( (b=i>>>23) == 0 ) {
b = top - a - 1;
- int m = b - v.narg();
+ int m = b - v.narg();
int j=1;
for ( ;j<=m; j++ )
o.set(offset+j, stack[a + j]);
@@ -482,11 +493,11 @@ public class LuaClosure extends LuaFunction {
if ( b == 0 ) {
top = a + (b = varargs.narg());
v = varargs;
- } else {
+ } else {
for ( int j=1; j= 0 && pc < p.lineinfo.length? String.valueOf(p.lineinfo[pc]): "?");
le.traceback = errorHook(le.getMessage(), le.level);
}
diff --git a/src/core/org/luaj/vm2/compiler/Constants.java b/src/core/org/luaj/vm2/compiler/Constants.java
index 50f2c2eb..fc505b49 100644
--- a/src/core/org/luaj/vm2/compiler/Constants.java
+++ b/src/core/org/luaj/vm2/compiler/Constants.java
@@ -46,20 +46,20 @@ public class Constants extends Lua {
/* OpMode - basic instruction format */
- static final int
+ static final int
iABC = 0,
iABx = 1,
iAsBx = 2;
/* OpArgMask */
- static final int
+ static final int
OpArgN = 0, /* argument is not used */
OpArgU = 1, /* argument is used */
OpArgR = 2, /* argument is a register or a jump offset */
OpArgK = 3; /* argument is a constant or register/constant */
- protected static void _assert(boolean b) {
+ protected static void _assert(boolean b) {
if (!b)
throw new LuaError("compiler assert failed");
}
@@ -104,6 +104,11 @@ public class Constants extends Lua {
((a << POS_A) & MASK_A) |
((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
@@ -150,7 +155,7 @@ public class Constants extends Lua {
}
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) {
diff --git a/src/core/org/luaj/vm2/compiler/FuncState.java b/src/core/org/luaj/vm2/compiler/FuncState.java
index b1d6f88d..70e0f885 100644
--- a/src/core/org/luaj/vm2/compiler/FuncState.java
+++ b/src/core/org/luaj/vm2/compiler/FuncState.java
@@ -580,11 +580,11 @@ public class FuncState extends Constants {
break;
}
case LexState.VK: {
- this.codeABx(OP_LOADK, reg, e.u.info);
+ this.codeK(reg, e.u.info);
break;
}
case LexState.VKNUM: {
- this.codeABx(OP_LOADK, reg, this.numberK(e.u.nval()));
+ this.codeK(reg, this.numberK(e.u.nval()));
break;
}
case LexState.VRELOCABLE: {
@@ -1116,6 +1116,20 @@ public class FuncState extends Constants {
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) {
int c = (nelems - 1) / LFIELDS_PER_FLUSH + 1;
diff --git a/src/core/org/luaj/vm2/compiler/LexState.java b/src/core/org/luaj/vm2/compiler/LexState.java
index c85cf68e..58864110 100644
--- a/src/core/org/luaj/vm2/compiler/LexState.java
+++ b/src/core/org/luaj/vm2/compiler/LexState.java
@@ -62,14 +62,14 @@ public class LexState extends Constants {
private static final int EOZ = (-1);
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 String LUA_QS(String s) { return "'"+s+"'"; }
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 boolean LUA_COMPAT_VARARG = true;
+ private static final boolean LUA_COMPAT_VARARG = true;
public static boolean isReservedKeyword(String 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
*/
- 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_CONCAT=6,
OPR_NE=7, OPR_EQ=8,
@@ -92,11 +92,11 @@ public class LexState extends Constants {
OPR_AND=13, OPR_OR=14,
OPR_NOBINOPR=15;
- static final int
+ static final int
OPR_MINUS=0, OPR_NOT=1, OPR_LEN=2, OPR_NOUNOPR=3;
/* exp kind */
- static final int
+ static final int
VVOID = 0, /* no value */
VNIL = 1,
VTRUE = 2,
@@ -153,14 +153,14 @@ public class LexState extends Constants {
"::", "", "", "", "", "",
};
- final static int
+ final static int
/* terminal symbols denoted by reserved words */
- 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_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_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,
/* 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;
final static int FIRST_RESERVED = TK_AND;
@@ -175,7 +175,7 @@ public class LexState extends Constants {
}
private boolean isalnum(int c) {
- return (c >= '0' && c <= '9')
+ return (c >= '0' && c <= '9')
|| (c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| (c == '_');
@@ -188,13 +188,13 @@ public class LexState extends Constants {
}
private boolean isdigit(int c) {
- return (c >= '0' && c <= '9');
+ return (c >= '0' && c <= '9');
}
private boolean isxdigit(int c) {
return (c >= '0' && c <= '9')
|| (c >= 'a' && c <= 'f')
- || (c >= 'A' && c <= 'F');
+ || (c >= 'A' && c <= 'F');
}
private boolean isspace(int c) {
@@ -235,7 +235,7 @@ public class LexState extends Constants {
String token2str( int token ) {
if ( token < FIRST_RESERVED ) {
- return iscntrl(token)?
+ return iscntrl(token)?
L.pushfstring( "char("+((int)token)+")" ):
L.pushfstring( String.valueOf( (char) token ) );
} else {
@@ -821,7 +821,7 @@ public class LexState extends Constants {
/* dynamic structures used by the parser */
static class Dyndata {
- Vardesc[] actvar; /* list of active local variables */
+ Vardesc[] actvar; /* list of active local variables */
int n_actvar = 0;
Labeldesc[] gt; /* list of pending gotos */
int n_gt = 0;
@@ -1610,7 +1610,7 @@ public class LexState extends Constants {
switch (t.token) {
case TK_ELSE: case TK_ELSEIF: case TK_END: case TK_EOS:
return true;
- case TK_UNTIL:
+ case TK_UNTIL:
return withuntil;
default: return false;
}
@@ -1634,7 +1634,7 @@ public class LexState extends Constants {
static class LHS_assign {
LHS_assign prev;
/* 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(','))
this.exp1(); /* optional step */
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);
}
this.forbody(base, line, 1, true);