Started with upgrading to Lua 5.3

This commit is contained in:
UnlegitDqrk
2026-03-01 21:42:19 +01:00
parent 01a8bd944e
commit 493b055a26
32 changed files with 1245 additions and 187 deletions

View File

@@ -89,11 +89,15 @@ public class Exp extends SyntaxElement {
case Lua.OP_OR: return 0;
case Lua.OP_AND: return 1;
case Lua.OP_LT: case Lua.OP_GT: case Lua.OP_LE: case Lua.OP_GE: case Lua.OP_NEQ: case Lua.OP_EQ: return 2;
case Lua.OP_CONCAT: return 3;
case Lua.OP_ADD: case Lua.OP_SUB: return 4;
case Lua.OP_MUL: case Lua.OP_DIV: case Lua.OP_IDIV: case Lua.OP_MOD: return 5;
case Lua.OP_NOT: case Lua.OP_UNM: case Lua.OP_LEN: return 6;
case Lua.OP_POW: return 7;
case Lua.OP_BOR: return 3;
case Lua.OP_BXOR: return 4;
case Lua.OP_BAND: return 5;
case Lua.OP_SHL: case Lua.OP_SHR: return 6;
case Lua.OP_CONCAT: return 7;
case Lua.OP_ADD: case Lua.OP_SUB: return 8;
case Lua.OP_MUL: case Lua.OP_DIV: case Lua.OP_IDIV: case Lua.OP_MOD: return 9;
case Lua.OP_NOT: case Lua.OP_UNM: case Lua.OP_LEN: case Lua.OP_BNOT: return 10;
case Lua.OP_POW: return 11;
default: throw new IllegalStateException("precedence of bad op "+op);
}
}

View File

@@ -78,7 +78,7 @@ public class CoerceJavaToLua {
private static final class IntCoercion implements Coercion {
public LuaValue coerce( Object javaValue ) {
Number n = (Number) javaValue;
return LuaInteger.valueOf( n.intValue() );
return LuaInteger.valueOf( n.longValue() );
}
}
@@ -149,7 +149,7 @@ public class CoerceJavaToLua {
COERCIONS.put( Character.class, charCoercion );
COERCIONS.put( Short.class, intCoercion );
COERCIONS.put( Integer.class, intCoercion );
COERCIONS.put( Long.class, doubleCoercion );
COERCIONS.put( Long.class, intCoercion );
COERCIONS.put( Float.class, doubleCoercion );
COERCIONS.put( Double.class, doubleCoercion );
COERCIONS.put( String.class, stringCoercion );
@@ -160,9 +160,9 @@ public class CoerceJavaToLua {
/**
* Coerse a Java object to a corresponding lua value.
* <p>
* Integral types {@code boolean}, {@code byte}, {@code char}, and {@code int}
* Integral types {@code boolean}, {@code byte}, {@code char}, {@code int}, and {@code long}
* will become {@link LuaInteger};
* {@code long}, {@code float}, and {@code double} will become {@link LuaDouble};
* {@code float} and {@code double} will become {@link LuaDouble};
* {@code String} and {@code byte[]} will become {@link LuaString};
* types inheriting from {@link LuaValue} will be returned without coercion;
* other types will become {@link LuaUserdata}.

View File

@@ -292,7 +292,10 @@ public class CoerceLuaToJava {
public int score(LuaValue value) {
switch ( value.type() ) {
case LuaValue.TNUMBER:
return inheritanceLevels( targetType, value.isint()? Integer.class: Double.class );
if (value.isinttype()) {
return inheritanceLevels( targetType, value.isint()? Integer.class: Long.class );
}
return inheritanceLevels( targetType, Double.class );
case LuaValue.TBOOLEAN:
return inheritanceLevels( targetType, Boolean.class );
case LuaValue.TSTRING:
@@ -308,7 +311,10 @@ public class CoerceLuaToJava {
public Object coerce(LuaValue value) {
switch ( value.type() ) {
case LuaValue.TNUMBER:
return value.isint()? (Object) Integer.valueOf(value.toint()): (Object) Double.valueOf(value.todouble());
if (value.isinttype()) {
return value.isint()? (Object) Integer.valueOf(value.toint()): (Object) Long.valueOf(value.tolong());
}
return Double.valueOf(value.todouble());
case LuaValue.TBOOLEAN:
return value.toboolean()? Boolean.TRUE: Boolean.FALSE;
case LuaValue.TSTRING:
@@ -369,4 +375,4 @@ public class CoerceLuaToJava {
COERCIONS.put( c, co );
return co;
}
}
}

View File

@@ -26,13 +26,13 @@ import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.libs.Bit32Lib;
import org.luaj.vm2.libs.CoroutineLib;
import org.luaj.vm2.libs.DebugLib;
import org.luaj.vm2.libs.PackageLib;
import org.luaj.vm2.libs.ResourceFinder;
import org.luaj.vm2.libs.StringLib;
import org.luaj.vm2.libs.TableLib;
import org.luaj.vm2.libs.Utf8Lib;
/** The {@link JsePlatform} class is a convenience class to standardize
* how globals tables are initialized for the JSE platform.
@@ -63,7 +63,6 @@ import org.luaj.vm2.libs.TableLib;
* <li>{@link Globals}</li>
* <li>{@link JseBaseLib}</li>
* <li>{@link PackageLib}</li>
* <li>{@link Bit32Lib}</li>
* <li>{@link TableLib}</li>
* <li>{@link StringLib}</li>
* <li>{@link CoroutineLib}</li>
@@ -95,9 +94,9 @@ public class JsePlatform {
Globals globals = new Globals();
globals.load(new JseBaseLib());
globals.load(new PackageLib());
globals.load(new Bit32Lib());
globals.load(new TableLib());
globals.load(new JseStringLib());
globals.load(new Utf8Lib());
globals.load(new CoroutineLib());
globals.load(new JseMathLib());
globals.load(new JseIoLib());

View File

@@ -520,6 +520,7 @@ public class JavaBuilder {
switch (o) {
default:
case Lua.OP_UNM: op = "neg"; break;
case Lua.OP_BNOT: op = "bnot"; break;
case Lua.OP_NOT: op = "not"; break;
case Lua.OP_LEN: op = "len"; break;
}
@@ -535,6 +536,11 @@ public class JavaBuilder {
case Lua.OP_MUL: op = "mul"; break;
case Lua.OP_DIV: op = "div"; break;
case Lua.OP_IDIV: op = "idiv"; break;
case Lua.OP_BAND: op = "band"; break;
case Lua.OP_BOR: op = "bor"; break;
case Lua.OP_BXOR: op = "bxor"; break;
case Lua.OP_SHL: op = "shl"; break;
case Lua.OP_SHR: op = "shr"; break;
case Lua.OP_MOD: op = "mod"; break;
case Lua.OP_POW: op = "pow"; break;
}

View File

@@ -112,6 +112,7 @@ public class JavaGen {
break;
case Lua.OP_UNM: /* A B R(A):= -R(B) */
case Lua.OP_BNOT: /* A B R(A):= ~R(B) */
case Lua.OP_NOT: /* A B R(A):= not R(B) */
case Lua.OP_LEN: /* A B R(A):= length of R(B) */
builder.loadLocal( pc, b );
@@ -166,6 +167,11 @@ public class JavaGen {
case Lua.OP_MUL: /* A B C R(A):= RK(B) * RK(C) */
case Lua.OP_DIV: /* A B C R(A):= RK(B) / RK(C) */
case Lua.OP_IDIV: /* A B C R(A):= RK(B) // RK(C) */
case Lua.OP_BAND: /* A B C R(A):= RK(B) & RK(C) */
case Lua.OP_BOR: /* A B C R(A):= RK(B) | RK(C) */
case Lua.OP_BXOR: /* A B C R(A):= RK(B) ~ RK(C) */
case Lua.OP_SHL: /* A B C R(A):= RK(B) << RK(C) */
case Lua.OP_SHR: /* A B C R(A):= RK(B) >> RK(C) */
case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */
case Lua.OP_POW: /* A B C R(A):= RK(B) ^ RK(C) */
loadLocalOrConstant( p, builder, pc, b );

View File

@@ -176,6 +176,7 @@ public class ProtoInfo {
case Lua.OP_MOVE:/* A B R(A) := R(B) */
case Lua.OP_UNM: /* A B R(A) := -R(B) */
case Lua.OP_BNOT: /* A B R(A) := ~R(B) */
case Lua.OP_NOT: /* A B R(A) := not R(B) */
case Lua.OP_LEN: /* A B R(A) := length of R(B) */
case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
@@ -190,6 +191,11 @@ public class ProtoInfo {
case Lua.OP_MUL: /* A B C R(A) := RK(B) * RK(C) */
case Lua.OP_DIV: /* A B C R(A) := RK(B) / RK(C) */
case Lua.OP_IDIV: /* A B C R(A) := RK(B) // RK(C) */
case Lua.OP_BAND: /* A B C R(A) := RK(B) & RK(C) */
case Lua.OP_BOR: /* A B C R(A) := RK(B) | RK(C) */
case Lua.OP_BXOR: /* A B C R(A) := RK(B) ~ RK(C) */
case Lua.OP_SHL: /* A B C R(A) := RK(B) << RK(C) */
case Lua.OP_SHR: /* A B C R(A) := RK(B) >> RK(C) */
case Lua.OP_MOD: /* A B C R(A) := RK(B) % RK(C) */
case Lua.OP_POW: /* A B C R(A) := RK(B) ^ RK(C) */
a = Lua.GETARG_A( ins );

View File

@@ -980,6 +980,26 @@ public class LuaParser implements LuaParserConstants {
jj_consume_token(85);
{if (true) return Lua.OP_DIV;}
break;
case BAND:
jj_consume_token(BAND);
{if (true) return Lua.OP_BAND;}
break;
case BOR:
jj_consume_token(BOR);
{if (true) return Lua.OP_BOR;}
break;
case BNOT:
jj_consume_token(BNOT);
{if (true) return Lua.OP_BXOR;}
break;
case SHL:
jj_consume_token(SHL);
{if (true) return Lua.OP_SHL;}
break;
case SHR:
jj_consume_token(SHR);
{if (true) return Lua.OP_SHR;}
break;
case 86:
jj_consume_token(86);
{if (true) return Lua.OP_POW;}
@@ -1046,6 +1066,10 @@ public class LuaParser implements LuaParserConstants {
jj_consume_token(69);
{if (true) return Lua.OP_LEN;}
break;
case BNOT:
jj_consume_token(BNOT);
{if (true) return Lua.OP_BNOT;}
break;
default:
jj_la1[33] = jj_gen;
jj_consume_token(-1);

View File

@@ -114,6 +114,16 @@ public interface LuaParserConstants {
int CHAR = 67;
/** RegularExpression Id. */
int LF = 68;
/** RegularExpression Id. */
int BNOT = 95;
/** RegularExpression Id. */
int BAND = 96;
/** RegularExpression Id. */
int BOR = 97;
/** RegularExpression Id. */
int SHL = 98;
/** RegularExpression Id. */
int SHR = 99;
/** Lexical state. */
int DEFAULT = 0;
@@ -237,6 +247,11 @@ public interface LuaParserConstants {
"\">=\"",
"\"==\"",
"\"~=\"",
"\"~\"",
"\"&\"",
"\"|\"",
"\"<<\"",
"\">>\"",
};
}

View File

@@ -450,6 +450,8 @@ private int jjMoveStringLiteralDfa0_0()
{
case 35:
return jjStopAtPos(0, 69);
case 38:
return jjStopAtPos(0, 96);
case 37:
return jjStopAtPos(0, 87);
case 40:
@@ -478,13 +480,13 @@ private int jjMoveStringLiteralDfa0_0()
return jjStopAtPos(0, 70);
case 60:
jjmatchedKind = 89;
return jjMoveStringLiteralDfa1_0(0x0L, 0x4000000L);
return jjMoveStringLiteralDfa1_0(0x0L, 0x84000000L);
case 61:
jjmatchedKind = 71;
return jjMoveStringLiteralDfa1_0(0x0L, 0x20000000L);
case 62:
jjmatchedKind = 91;
return jjMoveStringLiteralDfa1_0(0x0L, 0x10000000L);
return jjMoveStringLiteralDfa1_0(0x0L, 0x110000000L);
case 91:
jjmatchedKind = 77;
return jjMoveStringLiteralDfa1_0(0x7800L, 0x0L);
@@ -525,6 +527,7 @@ private int jjMoveStringLiteralDfa0_0()
case 125:
return jjStopAtPos(0, 81);
case 126:
jjmatchedKind = 95;
return jjMoveStringLiteralDfa1_0(0x0L, 0x40000000L);
default :
return jjMoveNfa_0(8, 0);
@@ -557,10 +560,18 @@ private int jjMoveStringLiteralDfa1_0(long active0, long active1)
if ((active1 & 0x1L) != 0L)
return jjStopAtPos(1, 28);
break;
case 60:
if ((active1 & 0x80000000L) != 0L)
return jjStopAtPos(1, 98);
break;
case 58:
if ((active1 & 0x2L) != 0L)
return jjStopAtPos(1, 65);
break;
case 62:
if ((active1 & 0x100000000L) != 0L)
return jjStopAtPos(1, 99);
break;
case 61:
if ((active1 & 0x4000000L) != 0L)
return jjStopAtPos(1, 90);
@@ -1759,7 +1770,7 @@ public static final int[] jjnewLexState = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
static final long[] jjtoToken = {
0x601fffffef800001L, 0x7fffffe2L,
0x601fffffef800001L, 0xfffffffe2L,
};
static final long[] jjtoSkip = {
0x7e003eL, 0x0L,
@@ -2105,3 +2116,5 @@ private void jjCheckNAddStates(int start, int end)
}
}
case 124:
return jjStopAtPos(0, 97);

View File

@@ -47,7 +47,7 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin
private static final String __NAME__ = "Luaj";
private static final String __SHORT_NAME__ = "Luaj";
private static final String __LANGUAGE__ = "lua";
private static final String __LANGUAGE_VERSION__ = "5.2";
private static final String __LANGUAGE_VERSION__ = "5.3";
private static final String __ARGV__ = "arg";
private static final String __FILENAME__ = "?";
@@ -244,7 +244,7 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin
case LuaValue.TSTRING: return luajValue.tojstring();
case LuaValue.TUSERDATA: return luajValue.checkuserdata(Object.class);
case LuaValue.TNUMBER: return luajValue.isinttype()?
(Object) Integer.valueOf(luajValue.toint()):
(Object) Long.valueOf(luajValue.tolong()):
(Object) Double.valueOf(luajValue.todouble());
default: return luajValue;
}
@@ -263,4 +263,4 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin
}
}
}
}

View File

@@ -116,6 +116,127 @@ public class FragmentsTest extends TestSuite {
public void testFloorDivisionInExpression() {
runFragment(LuaValue.TRUE, "local x=5 local width=10 return x==width//2\n");
}
public void testLongIntegerLiteralPrecision() {
runFragment(
LuaValue.varargsOf(new LuaValue[] {
LuaValue.valueOf(9007199254740993L),
LuaValue.valueOf(9007199254740994L),
LuaValue.valueOf(9007199254740992L)
}),
"local x = 9007199254740993\nreturn x, x + 1, x - 1\n");
}
public void testBitwiseOperators() {
runFragment(
LuaValue.varargsOf(new LuaValue[] {
LuaValue.valueOf(2),
LuaValue.valueOf(7),
LuaValue.valueOf(5),
LuaValue.valueOf(12),
LuaValue.valueOf(1),
LuaValue.valueOf(-6)
}),
"return 6 & 3, 6 | 3, 6 ~ 3, 3 << 2, 6 >> 2, ~5\n");
}
public void testBitwisePrecedence() {
runFragment(LuaValue.valueOf(7), "return 1 | 2 & 6\n");
}
public void testTableMove() {
runFragment(
LuaValue.varargsOf(new LuaValue[] {
LuaValue.valueOf(1),
LuaValue.valueOf(2),
LuaValue.valueOf(3),
LuaValue.valueOf(1),
LuaValue.valueOf(2),
LuaValue.valueOf(3)
}),
"local t = {1,2,3}\nlocal d = {}\ntable.move(t, 1, 3, 1, d)\nreturn d[1], d[2], d[3], table.move(t, 1, 3, 2)[2], t[3], t[4]\n");
}
public void testUtf8Library() {
runFragment(
LuaValue.varargsOf(new LuaValue[] {
LuaValue.valueOf(2),
LuaValue.valueOf(2),
LuaValue.valueOf(97),
LuaValue.valueOf(228),
LuaValue.valueOf(2)
}),
"local s = utf8.char(97, 228)\nlocal iter, state, var = utf8.codes(s)\nlocal _, cp = iter(state, var)\nreturn utf8.len(s), utf8.codepoint(s, 2), cp, utf8.offset(s, 2)\n");
}
public void testStringPackUnpack() {
runFragment(
LuaValue.varargsOf(new LuaValue[] {
LuaValue.valueOf(-5),
LuaValue.valueOf(513),
LuaValue.valueOf("hi"),
LuaValue.valueOf(10),
LuaValue.valueOf(7)
}),
"local s = string.pack('<i4I2z', -5, 513, 'hi')\nlocal a,b,c,n = string.unpack('<i4I2z', s)\nreturn a,b,c,n,string.packsize('<i4I2x')\n");
}
public void testStringPackFixedString() {
runFragment(
LuaValue.varargsOf(new LuaValue[] {
LuaValue.valueOf("ab\000\000"),
LuaValue.valueOf("ab\000\000"),
LuaValue.valueOf(5)
}),
"local s = string.pack('>c4', 'ab')\nreturn s, (string.unpack('>c4', s)), select(2, string.unpack('>c4', s))\n");
}
public void testMath53Helpers() {
runFragment(
LuaValue.varargsOf(new LuaValue[] {
LuaValue.valueOf("integer"),
LuaValue.valueOf(3),
LuaValue.TRUE,
LuaValue.valueOf(Long.MAX_VALUE),
LuaValue.valueOf(Long.MIN_VALUE),
LuaValue.valueOf("Lua 5.3")
}),
"return math.type(3), math.tointeger(3.0), math.ult(-1, 1), math.maxinteger, math.mininteger, _VERSION\n");
}
public void testHexFloatLiteralAndTonumber() {
runFragment(
LuaValue.varargsOf(new LuaValue[] {
LuaValue.valueOf(3.0),
LuaValue.valueOf(3.0),
LuaValue.valueOf(16)
}),
"return 0x1.8p1, tonumber('0x1.8p1'), tonumber('0x10')\n");
}
public void testCoroutineIsYieldable() {
runFragment(
LuaValue.varargsOf(new LuaValue[] {
LuaValue.FALSE,
LuaValue.TRUE
}),
"local co = coroutine.create(function() return coroutine.isyieldable() end)\n" +
"local ok, value = coroutine.resume(co)\n" +
"return coroutine.isyieldable(), value\n");
}
public void testMathRandomSupportsLongBounds() {
runFragment(
LuaValue.varargsOf(new LuaValue[] {
LuaValue.valueOf("integer"),
LuaValue.TRUE
}),
"math.randomseed(123)\nlocal v = math.random(9007199254740993, 9007199254740995)\nreturn math.type(v), v >= 9007199254740993 and v <= 9007199254740995\n");
}
public void testStandardGlobalsDoNotExposeBit32() {
runFragment(LuaValue.TRUE, "return bit32 == nil\n");
}
public void testForloopParamUpvalues() {
runFragment( LuaValue.varargsOf(new LuaValue[] {

View File

@@ -40,6 +40,20 @@ public class LuaJavaCoercionTest extends TestCase {
assertEquals( Integer.class, o.getClass() );
assertEquals( new Integer(777), o );
}
public void testJavaLongToLuaInteger() {
Long l = Long.valueOf(9007199254740993L);
LuaValue v = CoerceJavaToLua.coerce(l);
assertEquals( LuaInteger.class, v.getClass() );
assertEquals( 9007199254740993L, v.tolong() );
}
public void testLuaIntegerToJavaObjectUsesLongWhenNeeded() {
LuaInteger i = LuaInteger.valueOf(9007199254740993L);
Object o = CoerceLuaToJava.coerce(i, Object.class);
assertEquals( Long.class, o.getClass() );
assertEquals( Long.valueOf(9007199254740993L), o );
}
public void testJavaStringToLuaString() {
String s = new String("777");