Started with upgrading to Lua 5.3
This commit is contained in:
@@ -237,12 +237,12 @@ public class LoadState {
|
|||||||
|
|
||||||
int e = (int)((bits >> 52) & 0x7ffL) - 1023;
|
int e = (int)((bits >> 52) & 0x7ffL) - 1023;
|
||||||
|
|
||||||
if ( e >= 0 && e < 31 ) {
|
if ( e >= 0 && e < 63 ) {
|
||||||
long f = bits & 0xFFFFFFFFFFFFFL;
|
long f = bits & 0xFFFFFFFFFFFFFL;
|
||||||
int shift = 52 - e;
|
int shift = 52 - e;
|
||||||
long intPrecMask = ( 1L << shift ) - 1;
|
long intPrecMask = shift > 0 ? ( 1L << shift ) - 1 : 0;
|
||||||
if ( ( f & intPrecMask ) == 0 ) {
|
if ( shift <= 52 && ( f & intPrecMask ) == 0 ) {
|
||||||
int intValue = (int)( f >> shift ) | ( 1 << e );
|
long intValue = shift >= 0 ? (f >> shift) | (1L << e) : (f << (-shift)) | (1L << e);
|
||||||
return LuaInteger.valueOf( ( ( bits >> 63 ) != 0 ) ? -intValue : intValue );
|
return LuaInteger.valueOf( ( ( bits >> 63 ) != 0 ) ? -intValue : intValue );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ package org.luaj.vm2;
|
|||||||
*/
|
*/
|
||||||
public class Lua {
|
public class Lua {
|
||||||
/** version is supplied by ant build task */
|
/** version is supplied by ant build task */
|
||||||
public static final String _VERSION = "Luaj 0.0";
|
public static final String _VERSION = "Lua 5.3";
|
||||||
|
|
||||||
/** use return values from previous op */
|
/** use return values from previous op */
|
||||||
public static final int LUA_MULTRET = -1;
|
public static final int LUA_MULTRET = -1;
|
||||||
@@ -201,39 +201,45 @@ public class Lua {
|
|||||||
public static final int OP_MUL = 15; /* A B C R(A) := RK(B) * RK(C) */
|
public static final int OP_MUL = 15; /* A B C R(A) := RK(B) * RK(C) */
|
||||||
public static final int OP_DIV = 16; /* A B C R(A) := RK(B) / RK(C) */
|
public static final int OP_DIV = 16; /* A B C R(A) := RK(B) / RK(C) */
|
||||||
public static final int OP_IDIV = 17; /* A B C R(A) := RK(B) // RK(C) */
|
public static final int OP_IDIV = 17; /* A B C R(A) := RK(B) // RK(C) */
|
||||||
public static final int OP_MOD = 18; /* A B C R(A) := RK(B) % RK(C) */
|
public static final int OP_BAND = 18; /* A B C R(A) := RK(B) & RK(C) */
|
||||||
public static final int OP_POW = 19; /* A B C R(A) := RK(B) ^ RK(C) */
|
public static final int OP_BOR = 19; /* A B C R(A) := RK(B) | RK(C) */
|
||||||
public static final int OP_UNM = 20; /* A B R(A) := -R(B) */
|
public static final int OP_BXOR = 20; /* A B C R(A) := RK(B) ~ RK(C) */
|
||||||
public static final int OP_NOT = 21; /* A B R(A) := not R(B) */
|
public static final int OP_SHL = 21; /* A B C R(A) := RK(B) << RK(C) */
|
||||||
public static final int OP_LEN = 22; /* A B R(A) := length of R(B) */
|
public static final int OP_SHR = 22; /* A B C R(A) := RK(B) >> RK(C) */
|
||||||
|
public static final int OP_MOD = 23; /* A B C R(A) := RK(B) % RK(C) */
|
||||||
|
public static final int OP_POW = 24; /* A B C R(A) := RK(B) ^ RK(C) */
|
||||||
|
public static final int OP_UNM = 25; /* A B R(A) := -R(B) */
|
||||||
|
public static final int OP_BNOT = 26; /* A B R(A) := ~R(B) */
|
||||||
|
public static final int OP_NOT = 27; /* A B R(A) := not R(B) */
|
||||||
|
public static final int OP_LEN = 28; /* A B R(A) := length of R(B) */
|
||||||
|
|
||||||
public static final int OP_CONCAT = 23; /* A B C R(A) := R(B).. ... ..R(C) */
|
public static final int OP_CONCAT = 29; /* A B C R(A) := R(B).. ... ..R(C) */
|
||||||
|
|
||||||
public static final int OP_JMP = 24; /* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
|
public static final int OP_JMP = 30; /* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
|
||||||
public static final int OP_EQ = 25; /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
|
public static final int OP_EQ = 31; /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
|
||||||
public static final int OP_LT = 26; /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
|
public static final int OP_LT = 32; /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
|
||||||
public static final int OP_LE = 27; /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
|
public static final int OP_LE = 33; /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
|
||||||
|
|
||||||
public static final int OP_TEST = 28; /* A C if not (R(A) <=> C) then pc++ */
|
public static final int OP_TEST = 34; /* A C if not (R(A) <=> C) then pc++ */
|
||||||
public static final int OP_TESTSET = 29; /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
|
public static final int OP_TESTSET = 35; /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
|
||||||
|
|
||||||
public static final int OP_CALL = 30; /* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
|
public static final int OP_CALL = 36; /* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||||
public static final int OP_TAILCALL = 31; /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
|
public static final int OP_TAILCALL = 37; /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||||
public static final int OP_RETURN = 32; /* A B return R(A), ... ,R(A+B-2) (see note) */
|
public static final int OP_RETURN = 38; /* A B return R(A), ... ,R(A+B-2) (see note) */
|
||||||
|
|
||||||
public static final int OP_FORLOOP = 33; /* A sBx R(A)+=R(A+2);
|
public static final int OP_FORLOOP = 39; /* A sBx R(A)+=R(A+2);
|
||||||
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
|
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
|
||||||
public static final int OP_FORPREP = 34; /* A sBx R(A)-=R(A+2); pc+=sBx */
|
public static final int OP_FORPREP = 40; /* A sBx R(A)-=R(A+2); pc+=sBx */
|
||||||
|
|
||||||
public static final int OP_TFORCALL = 35; /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
|
public static final int OP_TFORCALL = 41; /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
|
||||||
public static final int OP_TFORLOOP = 36; /* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx } */
|
public static final int OP_TFORLOOP = 42; /* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx } */
|
||||||
public static final int OP_SETLIST = 37; /* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
|
public static final int OP_SETLIST = 43; /* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
|
||||||
|
|
||||||
public static final int OP_CLOSURE = 38; /* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
|
public static final int OP_CLOSURE = 44; /* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
|
||||||
|
|
||||||
public static final int OP_VARARG = 39; /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
|
public static final int OP_VARARG = 45; /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
|
||||||
|
|
||||||
public static final int OP_EXTRAARG = 40; /* Ax extra (larger) argument for previous opcode */
|
public static final int OP_EXTRAARG = 46; /* Ax extra (larger) argument for previous opcode */
|
||||||
|
|
||||||
public static final int NUM_OPCODES = OP_EXTRAARG + 1;
|
public static final int NUM_OPCODES = OP_EXTRAARG + 1;
|
||||||
|
|
||||||
@@ -299,9 +305,15 @@ public class Lua {
|
|||||||
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_MUL */
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_MUL */
|
||||||
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_DIV */
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_DIV */
|
||||||
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_IDIV */
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_IDIV */
|
||||||
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_BAND */
|
||||||
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_BOR */
|
||||||
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_BXOR */
|
||||||
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SHL */
|
||||||
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SHR */
|
||||||
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_MOD */
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_MOD */
|
||||||
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_POW */
|
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_POW */
|
||||||
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_UNM */
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_UNM */
|
||||||
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_BNOT */
|
||||||
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_NOT */
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_NOT */
|
||||||
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_LEN */
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_LEN */
|
||||||
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgR<<2) | (iABC), /* OP_CONCAT */
|
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgR<<2) | (iABC), /* OP_CONCAT */
|
||||||
|
|||||||
@@ -352,6 +352,26 @@ public class LuaClosure extends LuaFunction {
|
|||||||
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).idiv((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
|
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).idiv((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
case Lua.OP_BAND: /* A B C R(A):= RK(B) & RK(C) */
|
||||||
|
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).band((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case Lua.OP_BOR: /* A B C R(A):= RK(B) | RK(C) */
|
||||||
|
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).bor((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case Lua.OP_BXOR: /* A B C R(A):= RK(B) ~ RK(C) */
|
||||||
|
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).bxor((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case Lua.OP_SHL: /* A B C R(A):= RK(B) << RK(C) */
|
||||||
|
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).shl((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case Lua.OP_SHR: /* A B C R(A):= RK(B) >> RK(C) */
|
||||||
|
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).shr((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
|
||||||
|
continue;
|
||||||
|
|
||||||
case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */
|
case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */
|
||||||
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mod((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
|
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mod((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
|
||||||
continue;
|
continue;
|
||||||
@@ -364,6 +384,10 @@ public class LuaClosure extends LuaFunction {
|
|||||||
stack[a] = stack[i>>>23].neg();
|
stack[a] = stack[i>>>23].neg();
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
case Lua.OP_BNOT: /* A B R(A):= ~R(B) */
|
||||||
|
stack[a] = stack[i>>>23].bnot();
|
||||||
|
continue;
|
||||||
|
|
||||||
case Lua.OP_NOT: /* A B R(A):= not R(B) */
|
case Lua.OP_NOT: /* A B R(A):= not R(B) */
|
||||||
stack[a] = stack[i>>>23].not();
|
stack[a] = stack[i>>>23].not();
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -75,8 +75,13 @@ public class LuaDouble extends LuaNumber {
|
|||||||
final double v;
|
final double v;
|
||||||
|
|
||||||
public static LuaNumber valueOf(double d) {
|
public static LuaNumber valueOf(double d) {
|
||||||
int id = (int) d;
|
if (!Double.isNaN(d) && !Double.isInfinite(d) && d >= Long.MIN_VALUE && d <= Long.MAX_VALUE) {
|
||||||
return d==id? (LuaNumber) LuaInteger.valueOf(id): (LuaNumber) new LuaDouble(d);
|
long ld = (long) d;
|
||||||
|
if (d == ld) {
|
||||||
|
return LuaInteger.valueOf(ld);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new LuaDouble(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Don't allow ints to be boxed by DoubleValues */
|
/** Don't allow ints to be boxed by DoubleValues */
|
||||||
@@ -103,13 +108,14 @@ public class LuaDouble extends LuaNumber {
|
|||||||
|
|
||||||
public double optdouble(double defval) { return v; }
|
public double optdouble(double defval) { return v; }
|
||||||
public int optint(int defval) { return (int) (long) v; }
|
public int optint(int defval) { return (int) (long) v; }
|
||||||
public LuaInteger optinteger(LuaInteger defval) { return LuaInteger.valueOf((int) (long)v); }
|
public LuaInteger optinteger(LuaInteger defval) { return islong()? LuaInteger.valueOf((long) v): defval; }
|
||||||
public long optlong(long defval) { return (long) v; }
|
public long optlong(long defval) { return (long) v; }
|
||||||
|
|
||||||
public LuaInteger checkinteger() { return LuaInteger.valueOf( (int) (long) v ); }
|
public LuaInteger checkinteger() { if (!islong()) argerror("integer"); return LuaInteger.valueOf((long) v); }
|
||||||
|
|
||||||
// unary operators
|
// unary operators
|
||||||
public LuaValue neg() { return valueOf(-v); }
|
public LuaValue neg() { return valueOf(-v); }
|
||||||
|
public LuaValue bnot() { if (!islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(~((long) v)); }
|
||||||
|
|
||||||
// object equality, used for key comparison
|
// object equality, used for key comparison
|
||||||
public boolean equals(Object o) { return o instanceof LuaDouble? ((LuaDouble)o).v == v: false; }
|
public boolean equals(Object o) { return o instanceof LuaDouble? ((LuaDouble)o).v == v: false; }
|
||||||
@@ -122,6 +128,7 @@ public class LuaDouble extends LuaNumber {
|
|||||||
public boolean raweq( LuaValue val ) { return val.raweq(v); }
|
public boolean raweq( LuaValue val ) { return val.raweq(v); }
|
||||||
public boolean raweq( double val ) { return v == val; }
|
public boolean raweq( double val ) { return v == val; }
|
||||||
public boolean raweq( int val ) { return v == val; }
|
public boolean raweq( int val ) { return v == val; }
|
||||||
|
public boolean raweq( long val ) { return v == val; }
|
||||||
|
|
||||||
// basic binary arithmetic
|
// basic binary arithmetic
|
||||||
public LuaValue add( LuaValue rhs ) { return rhs.add(v); }
|
public LuaValue add( LuaValue rhs ) { return rhs.add(v); }
|
||||||
@@ -146,6 +153,11 @@ public class LuaDouble extends LuaNumber {
|
|||||||
public LuaValue idiv( double rhs ) { return LuaDouble.didiv(v,rhs); }
|
public LuaValue idiv( double rhs ) { return LuaDouble.didiv(v,rhs); }
|
||||||
public LuaValue idiv( int rhs ) { return LuaDouble.didiv(v,rhs); }
|
public LuaValue idiv( int rhs ) { return LuaDouble.didiv(v,rhs); }
|
||||||
public LuaValue idivInto( double lhs ) { return LuaDouble.didiv(lhs,v); }
|
public LuaValue idivInto( double lhs ) { return LuaDouble.didiv(lhs,v); }
|
||||||
|
public LuaValue band( LuaValue rhs ) { if (!islong()) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.band(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(((long) v) & n.tolong()); }
|
||||||
|
public LuaValue bor( LuaValue rhs ) { if (!islong()) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.bor(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(((long) v) | n.tolong()); }
|
||||||
|
public LuaValue bxor( LuaValue rhs ) { if (!islong()) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.bxor(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(((long) v) ^ n.tolong()); }
|
||||||
|
public LuaValue shl( LuaValue rhs ) { if (!islong()) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.shl(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(LuaInteger.luaShiftLeft((long) v, n.tolong())); }
|
||||||
|
public LuaValue shr( LuaValue rhs ) { if (!islong()) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.shr(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(LuaInteger.luaShiftRight((long) v, n.tolong())); }
|
||||||
public LuaValue mod( LuaValue rhs ) { return rhs.modFrom(v); }
|
public LuaValue mod( LuaValue rhs ) { return rhs.modFrom(v); }
|
||||||
public LuaValue mod( double rhs ) { return LuaDouble.dmod(v,rhs); }
|
public LuaValue mod( double rhs ) { return LuaDouble.dmod(v,rhs); }
|
||||||
public LuaValue mod( int rhs ) { return LuaDouble.dmod(v,rhs); }
|
public LuaValue mod( int rhs ) { return LuaDouble.dmod(v,rhs); }
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ package org.luaj.vm2;
|
|||||||
import org.luaj.vm2.libs.MathLib;
|
import org.luaj.vm2.libs.MathLib;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension of {@link LuaNumber} which can hold a Java int as its value.
|
* Extension of {@link LuaNumber} which can hold a Java long as its value.
|
||||||
* <p>
|
* <p>
|
||||||
* These instance are not instantiated directly by clients, but indirectly
|
* These instance are not instantiated directly by clients, but indirectly
|
||||||
* via the static functions {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(double)}
|
* via the static functions {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(double)}
|
||||||
@@ -59,25 +59,23 @@ public class LuaInteger extends LuaNumber {
|
|||||||
* @see LuaValue#valueOf(int)
|
* @see LuaValue#valueOf(int)
|
||||||
* @see LuaValue#valueOf(double)
|
* @see LuaValue#valueOf(double)
|
||||||
*/
|
*/
|
||||||
public static LuaNumber valueOf(long l) {
|
public static LuaInteger valueOf(long l) {
|
||||||
int i = (int) l;
|
int i = (int) l;
|
||||||
return l==i? (i<=255 && i>=-256? intValues[i+256]:
|
return l == i && i <= 255 && i >= -256 ? intValues[i+256] : new LuaInteger(l);
|
||||||
(LuaNumber) new LuaInteger(i)):
|
|
||||||
(LuaNumber) LuaDouble.valueOf(l);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The value being held by this instance. */
|
/** The value being held by this instance. */
|
||||||
public final int v;
|
public final long v;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package protected constructor.
|
* Package protected constructor.
|
||||||
* @see LuaValue#valueOf(int)
|
* @see LuaValue#valueOf(int)
|
||||||
**/
|
**/
|
||||||
LuaInteger(int i) {
|
LuaInteger(long i) {
|
||||||
this.v = i;
|
this.v = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isint() { return true; }
|
public boolean isint() { return v == (int) v; }
|
||||||
public boolean isinttype() { return true; }
|
public boolean isinttype() { return true; }
|
||||||
public boolean islong() { return true; }
|
public boolean islong() { return true; }
|
||||||
|
|
||||||
@@ -85,33 +83,33 @@ public class LuaInteger extends LuaNumber {
|
|||||||
public char tochar() { return (char) v; }
|
public char tochar() { return (char) v; }
|
||||||
public double todouble() { return v; }
|
public double todouble() { return v; }
|
||||||
public float tofloat() { return v; }
|
public float tofloat() { return v; }
|
||||||
public int toint() { return v; }
|
public int toint() { return (int) v; }
|
||||||
public long tolong() { return v; }
|
public long tolong() { return v; }
|
||||||
public short toshort() { return (short) v; }
|
public short toshort() { return (short) v; }
|
||||||
|
|
||||||
public double optdouble(double defval) { return v; }
|
public double optdouble(double defval) { return v; }
|
||||||
public int optint(int defval) { return v; }
|
public int optint(int defval) { return (int) v; }
|
||||||
public LuaInteger optinteger(LuaInteger defval) { return this; }
|
public LuaInteger optinteger(LuaInteger defval) { return this; }
|
||||||
public long optlong(long defval) { return v; }
|
public long optlong(long defval) { return v; }
|
||||||
|
|
||||||
public String tojstring() {
|
public String tojstring() {
|
||||||
return Integer.toString(v);
|
return Long.toString(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaString strvalue() {
|
public LuaString strvalue() {
|
||||||
return LuaString.valueOf(Integer.toString(v));
|
return LuaString.valueOf(Long.toString(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaString optstring(LuaString defval) {
|
public LuaString optstring(LuaString defval) {
|
||||||
return LuaString.valueOf(Integer.toString(v));
|
return LuaString.valueOf(Long.toString(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue tostring() {
|
public LuaValue tostring() {
|
||||||
return LuaString.valueOf(Integer.toString(v));
|
return LuaString.valueOf(Long.toString(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String optjstring(String defval) {
|
public String optjstring(String defval) {
|
||||||
return Integer.toString(v);
|
return Long.toString(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaInteger checkinteger() {
|
public LuaInteger checkinteger() {
|
||||||
@@ -123,15 +121,16 @@ public class LuaInteger extends LuaNumber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return v;
|
return hashCode(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int hashCode(int x) {
|
public static int hashCode(long x) {
|
||||||
return x;
|
return (int) (x ^ (x >>> 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
// unary operators
|
// unary operators
|
||||||
public LuaValue neg() { return valueOf(-(long)v); }
|
public LuaValue neg() { return valueOf(-(long)v); }
|
||||||
|
public LuaValue bnot() { return valueOf(~v); }
|
||||||
|
|
||||||
// object equality, used for key comparison
|
// object equality, used for key comparison
|
||||||
public boolean equals(Object o) { return o instanceof LuaInteger? ((LuaInteger)o).v == v: false; }
|
public boolean equals(Object o) { return o instanceof LuaInteger? ((LuaInteger)o).v == v: false; }
|
||||||
@@ -144,60 +143,66 @@ public class LuaInteger extends LuaNumber {
|
|||||||
public boolean raweq( LuaValue val ) { return val.raweq(v); }
|
public boolean raweq( LuaValue val ) { return val.raweq(v); }
|
||||||
public boolean raweq( double val ) { return v == val; }
|
public boolean raweq( double val ) { return v == val; }
|
||||||
public boolean raweq( int val ) { return v == val; }
|
public boolean raweq( int val ) { return v == val; }
|
||||||
|
public boolean raweq( long val ) { return v == val; }
|
||||||
|
|
||||||
// arithmetic operators
|
// arithmetic operators
|
||||||
public LuaValue add( LuaValue rhs ) { return rhs.add(v); }
|
public LuaValue add( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.add(rhs): (n.isinttype()? LuaInteger.valueOf(v + n.tolong()): LuaDouble.valueOf(v + n.todouble())); }
|
||||||
public LuaValue add( double lhs ) { return LuaDouble.valueOf(lhs + v); }
|
public LuaValue add( double lhs ) { return LuaDouble.valueOf(lhs + v); }
|
||||||
public LuaValue add( int lhs ) { return LuaInteger.valueOf(lhs + (long)v); }
|
public LuaValue add( int lhs ) { return LuaInteger.valueOf(lhs + v); }
|
||||||
public LuaValue sub( LuaValue rhs ) { return rhs.subFrom(v); }
|
public LuaValue sub( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.sub(rhs): (n.isinttype()? LuaInteger.valueOf(v - n.tolong()): LuaDouble.valueOf(v - n.todouble())); }
|
||||||
public LuaValue sub( double rhs ) { return LuaDouble.valueOf(v - rhs); }
|
public LuaValue sub( double rhs ) { return LuaDouble.valueOf(v - rhs); }
|
||||||
public LuaValue sub( int rhs ) { return LuaDouble.valueOf(v - rhs); }
|
public LuaValue sub( int rhs ) { return LuaInteger.valueOf(v - rhs); }
|
||||||
public LuaValue subFrom( double lhs ) { return LuaDouble.valueOf(lhs - v); }
|
public LuaValue subFrom( double lhs ) { return LuaDouble.valueOf(lhs - v); }
|
||||||
public LuaValue subFrom( int lhs ) { return LuaInteger.valueOf(lhs - (long)v); }
|
public LuaValue subFrom( int lhs ) { return LuaInteger.valueOf(lhs - v); }
|
||||||
public LuaValue mul( LuaValue rhs ) { return rhs.mul(v); }
|
public LuaValue mul( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.mul(rhs): (n.isinttype()? LuaInteger.valueOf(v * n.tolong()): LuaDouble.valueOf(v * n.todouble())); }
|
||||||
public LuaValue mul( double lhs ) { return LuaDouble.valueOf(lhs * v); }
|
public LuaValue mul( double lhs ) { return LuaDouble.valueOf(lhs * v); }
|
||||||
public LuaValue mul( int lhs ) { return LuaInteger.valueOf(lhs * (long)v); }
|
public LuaValue mul( int lhs ) { return LuaInteger.valueOf(lhs * v); }
|
||||||
public LuaValue pow( LuaValue rhs ) { return rhs.powWith(v); }
|
public LuaValue pow( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.pow(rhs): MathLib.dpow(v, n.todouble()); }
|
||||||
public LuaValue pow( double rhs ) { return MathLib.dpow(v,rhs); }
|
public LuaValue pow( double rhs ) { return MathLib.dpow(v,rhs); }
|
||||||
public LuaValue pow( int rhs ) { return MathLib.dpow(v,rhs); }
|
public LuaValue pow( int rhs ) { return MathLib.dpow(v,rhs); }
|
||||||
public LuaValue powWith( double lhs ) { return MathLib.dpow(lhs,v); }
|
public LuaValue powWith( double lhs ) { return MathLib.dpow(lhs,v); }
|
||||||
public LuaValue powWith( int lhs ) { return MathLib.dpow(lhs,v); }
|
public LuaValue powWith( int lhs ) { return MathLib.dpow(lhs,v); }
|
||||||
public LuaValue div( LuaValue rhs ) { return rhs.divInto(v); }
|
public LuaValue div( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.div(rhs): LuaDouble.ddiv(v, n.todouble()); }
|
||||||
public LuaValue idiv( LuaValue rhs ) { return rhs.idivInto(v); }
|
public LuaValue idiv( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.idiv(rhs): (n.isinttype()? LuaInteger.valueOf(luaFloorDiv(v, n.tolong())): LuaDouble.didiv(v, n.todouble())); }
|
||||||
public LuaValue div( double rhs ) { return LuaDouble.ddiv(v,rhs); }
|
public LuaValue div( double rhs ) { return LuaDouble.ddiv(v,rhs); }
|
||||||
public LuaValue div( int rhs ) { return LuaDouble.ddiv(v,rhs); }
|
public LuaValue div( int rhs ) { return LuaDouble.ddiv(v,rhs); }
|
||||||
public LuaValue divInto( double lhs ) { return LuaDouble.ddiv(lhs,v); }
|
public LuaValue divInto( double lhs ) { return LuaDouble.ddiv(lhs,v); }
|
||||||
public LuaValue idiv( double rhs ) { return LuaDouble.didiv(v,rhs); }
|
public LuaValue idiv( double rhs ) { return LuaDouble.didiv(v,rhs); }
|
||||||
public LuaValue idiv( int rhs ) { return LuaDouble.didiv(v,rhs); }
|
public LuaValue idiv( int rhs ) { return LuaInteger.valueOf(luaFloorDiv(v, rhs)); }
|
||||||
public LuaValue idivInto( double lhs ) { return LuaDouble.didiv(lhs,v); }
|
public LuaValue idivInto( double lhs ) { return LuaDouble.didiv(lhs,v); }
|
||||||
public LuaValue mod( LuaValue rhs ) { return rhs.modFrom(v); }
|
public LuaValue band( LuaValue rhs ) { LuaValue n = rhs.tonumber(); if (n.isnil()) return super.band(rhs); if (!n.islong()) throw bitwiseError(); return LuaInteger.valueOf(v & n.tolong()); }
|
||||||
|
public LuaValue bor( LuaValue rhs ) { LuaValue n = rhs.tonumber(); if (n.isnil()) return super.bor(rhs); if (!n.islong()) throw bitwiseError(); return LuaInteger.valueOf(v | n.tolong()); }
|
||||||
|
public LuaValue bxor( LuaValue rhs ) { LuaValue n = rhs.tonumber(); if (n.isnil()) return super.bxor(rhs); if (!n.islong()) throw bitwiseError(); return LuaInteger.valueOf(v ^ n.tolong()); }
|
||||||
|
public LuaValue shl( LuaValue rhs ) { LuaValue n = rhs.tonumber(); if (n.isnil()) return super.shl(rhs); if (!n.islong()) throw bitwiseError(); return LuaInteger.valueOf(luaShiftLeft(v, n.tolong())); }
|
||||||
|
public LuaValue shr( LuaValue rhs ) { LuaValue n = rhs.tonumber(); if (n.isnil()) return super.shr(rhs); if (!n.islong()) throw bitwiseError(); return LuaInteger.valueOf(luaShiftRight(v, n.tolong())); }
|
||||||
|
public LuaValue mod( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.mod(rhs): (n.isinttype()? LuaInteger.valueOf(luaFloorMod(v, n.tolong())): LuaDouble.dmod(v, n.todouble())); }
|
||||||
public LuaValue mod( double rhs ) { return LuaDouble.dmod(v,rhs); }
|
public LuaValue mod( double rhs ) { return LuaDouble.dmod(v,rhs); }
|
||||||
public LuaValue mod( int rhs ) { return LuaDouble.dmod(v,rhs); }
|
public LuaValue mod( int rhs ) { return LuaInteger.valueOf(luaFloorMod(v, rhs)); }
|
||||||
public LuaValue modFrom( double lhs ) { return LuaDouble.dmod(lhs,v); }
|
public LuaValue modFrom( double lhs ) { return LuaDouble.dmod(lhs,v); }
|
||||||
|
|
||||||
// relational operators
|
// relational operators
|
||||||
public LuaValue lt( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.gt_b(v)? TRUE: FALSE) : super.lt(rhs); }
|
public LuaValue lt( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.lt(rhs): (n.isinttype()? (v < n.tolong()? TRUE: FALSE): (v < n.todouble()? TRUE: FALSE)); }
|
||||||
public LuaValue lt( double rhs ) { return v < rhs? TRUE: FALSE; }
|
public LuaValue lt( double rhs ) { return v < rhs? TRUE: FALSE; }
|
||||||
public LuaValue lt( int rhs ) { return v < rhs? TRUE: FALSE; }
|
public LuaValue lt( int rhs ) { return v < rhs? TRUE: FALSE; }
|
||||||
public boolean lt_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.gt_b(v) : super.lt_b(rhs); }
|
public boolean lt_b( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.lt_b(rhs): (n.isinttype()? v < n.tolong(): v < n.todouble()); }
|
||||||
public boolean lt_b( int rhs ) { return v < rhs; }
|
public boolean lt_b( int rhs ) { return v < rhs; }
|
||||||
public boolean lt_b( double rhs ) { return v < rhs; }
|
public boolean lt_b( double rhs ) { return v < rhs; }
|
||||||
public LuaValue lteq( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.gteq_b(v)? TRUE: FALSE) : super.lteq(rhs); }
|
public LuaValue lteq( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.lteq(rhs): (n.isinttype()? (v <= n.tolong()? TRUE: FALSE): (v <= n.todouble()? TRUE: FALSE)); }
|
||||||
public LuaValue lteq( double rhs ) { return v <= rhs? TRUE: FALSE; }
|
public LuaValue lteq( double rhs ) { return v <= rhs? TRUE: FALSE; }
|
||||||
public LuaValue lteq( int rhs ) { return v <= rhs? TRUE: FALSE; }
|
public LuaValue lteq( int rhs ) { return v <= rhs? TRUE: FALSE; }
|
||||||
public boolean lteq_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.gteq_b(v) : super.lteq_b(rhs); }
|
public boolean lteq_b( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.lteq_b(rhs): (n.isinttype()? v <= n.tolong(): v <= n.todouble()); }
|
||||||
public boolean lteq_b( int rhs ) { return v <= rhs; }
|
public boolean lteq_b( int rhs ) { return v <= rhs; }
|
||||||
public boolean lteq_b( double rhs ) { return v <= rhs; }
|
public boolean lteq_b( double rhs ) { return v <= rhs; }
|
||||||
public LuaValue gt( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.lt_b(v)? TRUE: FALSE) : super.gt(rhs); }
|
public LuaValue gt( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.gt(rhs): (n.isinttype()? (v > n.tolong()? TRUE: FALSE): (v > n.todouble()? TRUE: FALSE)); }
|
||||||
public LuaValue gt( double rhs ) { return v > rhs? TRUE: FALSE; }
|
public LuaValue gt( double rhs ) { return v > rhs? TRUE: FALSE; }
|
||||||
public LuaValue gt( int rhs ) { return v > rhs? TRUE: FALSE; }
|
public LuaValue gt( int rhs ) { return v > rhs? TRUE: FALSE; }
|
||||||
public boolean gt_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.lt_b(v) : super.gt_b(rhs); }
|
public boolean gt_b( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.gt_b(rhs): (n.isinttype()? v > n.tolong(): v > n.todouble()); }
|
||||||
public boolean gt_b( int rhs ) { return v > rhs; }
|
public boolean gt_b( int rhs ) { return v > rhs; }
|
||||||
public boolean gt_b( double rhs ) { return v > rhs; }
|
public boolean gt_b( double rhs ) { return v > rhs; }
|
||||||
public LuaValue gteq( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.lteq_b(v)? TRUE: FALSE) : super.gteq(rhs); }
|
public LuaValue gteq( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.gteq(rhs): (n.isinttype()? (v >= n.tolong()? TRUE: FALSE): (v >= n.todouble()? TRUE: FALSE)); }
|
||||||
public LuaValue gteq( double rhs ) { return v >= rhs? TRUE: FALSE; }
|
public LuaValue gteq( double rhs ) { return v >= rhs? TRUE: FALSE; }
|
||||||
public LuaValue gteq( int rhs ) { return v >= rhs? TRUE: FALSE; }
|
public LuaValue gteq( int rhs ) { return v >= rhs? TRUE: FALSE; }
|
||||||
public boolean gteq_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.lteq_b(v) : super.gteq_b(rhs); }
|
public boolean gteq_b( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.gteq_b(rhs): (n.isinttype()? v >= n.tolong(): v >= n.todouble()); }
|
||||||
public boolean gteq_b( int rhs ) { return v >= rhs; }
|
public boolean gteq_b( int rhs ) { return v >= rhs; }
|
||||||
public boolean gteq_b( double rhs ) { return v >= rhs; }
|
public boolean gteq_b( double rhs ) { return v >= rhs; }
|
||||||
|
|
||||||
@@ -205,7 +210,7 @@ public class LuaInteger extends LuaNumber {
|
|||||||
public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; }
|
public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; }
|
||||||
|
|
||||||
public int checkint() {
|
public int checkint() {
|
||||||
return v;
|
return (int) v;
|
||||||
}
|
}
|
||||||
public long checklong() {
|
public long checklong() {
|
||||||
return v;
|
return v;
|
||||||
@@ -220,4 +225,41 @@ public class LuaInteger extends LuaNumber {
|
|||||||
return valueOf( String.valueOf(v) );
|
return valueOf( String.valueOf(v) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static long luaFloorDiv(long lhs, long rhs) {
|
||||||
|
if (rhs == 0) {
|
||||||
|
throw new LuaError("attempt to divide by zero");
|
||||||
|
}
|
||||||
|
long quotient = lhs / rhs;
|
||||||
|
long remainder = lhs % rhs;
|
||||||
|
if (remainder != 0 && ((lhs ^ rhs) < 0)) {
|
||||||
|
quotient--;
|
||||||
|
}
|
||||||
|
return quotient;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long luaFloorMod(long lhs, long rhs) {
|
||||||
|
if (rhs == 0) {
|
||||||
|
throw new LuaError("attempt to divide by zero");
|
||||||
|
}
|
||||||
|
return lhs - rhs * luaFloorDiv(lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long luaShiftLeft(long lhs, long rhs) {
|
||||||
|
if (rhs < 0) {
|
||||||
|
return luaShiftRight(lhs, -rhs);
|
||||||
|
}
|
||||||
|
return rhs >= Long.SIZE ? 0L : lhs << rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long luaShiftRight(long lhs, long rhs) {
|
||||||
|
if (rhs < 0) {
|
||||||
|
return luaShiftLeft(lhs, -rhs);
|
||||||
|
}
|
||||||
|
return rhs >= Long.SIZE ? 0L : lhs >>> rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LuaError bitwiseError() {
|
||||||
|
return new LuaError("number has no integer representation");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -262,6 +262,7 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
// unary operators
|
// unary operators
|
||||||
public LuaValue neg() { double d = scannumber(); return Double.isNaN(d)? super.neg(): valueOf(-d); }
|
public LuaValue neg() { double d = scannumber(); return Double.isNaN(d)? super.neg(): valueOf(-d); }
|
||||||
|
public LuaValue bnot() { double d = scannumber(); if (Double.isNaN(d)) return super.bnot(); if (d != (long) d) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(~((long) d)); }
|
||||||
|
|
||||||
// basic binary arithmetic
|
// basic binary arithmetic
|
||||||
public LuaValue add( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(ADD,rhs): rhs.add(d); }
|
public LuaValue add( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(ADD,rhs): rhs.add(d); }
|
||||||
@@ -287,6 +288,11 @@ public class LuaString extends LuaValue {
|
|||||||
public LuaValue idiv( double rhs ) { return LuaDouble.didiv(checkarith(),rhs); }
|
public LuaValue idiv( double rhs ) { return LuaDouble.didiv(checkarith(),rhs); }
|
||||||
public LuaValue idiv( int rhs ) { return LuaDouble.didiv(checkarith(),rhs); }
|
public LuaValue idiv( int rhs ) { return LuaDouble.didiv(checkarith(),rhs); }
|
||||||
public LuaValue idivInto( double lhs ) { return LuaDouble.didiv(lhs, checkarith()); }
|
public LuaValue idivInto( double lhs ) { return LuaDouble.didiv(lhs, checkarith()); }
|
||||||
|
public LuaValue band( LuaValue rhs ) { double d = scannumber(); if (Double.isNaN(d)) return super.band(rhs); if (d != (long) d) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.band(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(((long) d) & n.tolong()); }
|
||||||
|
public LuaValue bor( LuaValue rhs ) { double d = scannumber(); if (Double.isNaN(d)) return super.bor(rhs); if (d != (long) d) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.bor(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(((long) d) | n.tolong()); }
|
||||||
|
public LuaValue bxor( LuaValue rhs ) { double d = scannumber(); if (Double.isNaN(d)) return super.bxor(rhs); if (d != (long) d) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.bxor(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(((long) d) ^ n.tolong()); }
|
||||||
|
public LuaValue shl( LuaValue rhs ) { double d = scannumber(); if (Double.isNaN(d)) return super.shl(rhs); if (d != (long) d) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.shl(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(LuaInteger.luaShiftLeft((long) d, n.tolong())); }
|
||||||
|
public LuaValue shr( LuaValue rhs ) { double d = scannumber(); if (Double.isNaN(d)) return super.shr(rhs); if (d != (long) d) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.shr(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(LuaInteger.luaShiftRight((long) d, n.tolong())); }
|
||||||
public LuaValue mod( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(MOD,rhs): rhs.modFrom(d); }
|
public LuaValue mod( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(MOD,rhs): rhs.modFrom(d); }
|
||||||
public LuaValue mod( double rhs ) { return LuaDouble.dmod(checkarith(), rhs); }
|
public LuaValue mod( double rhs ) { return LuaDouble.dmod(checkarith(), rhs); }
|
||||||
public LuaValue mod( int rhs ) { return LuaDouble.dmod(checkarith(), rhs); }
|
public LuaValue mod( int rhs ) { return LuaDouble.dmod(checkarith(), rhs); }
|
||||||
@@ -344,10 +350,16 @@ public class LuaString extends LuaValue {
|
|||||||
return (int) (long) checkdouble();
|
return (int) (long) checkdouble();
|
||||||
}
|
}
|
||||||
public LuaInteger checkinteger() {
|
public LuaInteger checkinteger() {
|
||||||
return valueOf(checkint());
|
double d = scannumber();
|
||||||
|
if (Double.isNaN(d) || d != (long) d)
|
||||||
|
argerror("integer");
|
||||||
|
return LuaInteger.valueOf((long) d);
|
||||||
}
|
}
|
||||||
public long checklong() {
|
public long checklong() {
|
||||||
return (long) checkdouble();
|
double d = scannumber();
|
||||||
|
if (Double.isNaN(d) || d != (long) d)
|
||||||
|
argerror("integer");
|
||||||
|
return (long) d;
|
||||||
}
|
}
|
||||||
public double checkdouble() {
|
public double checkdouble() {
|
||||||
double d = scannumber();
|
double d = scannumber();
|
||||||
@@ -765,8 +777,11 @@ public class LuaString extends LuaValue {
|
|||||||
while ( i<j && m_bytes[j-1]==' ' ) --j;
|
while ( i<j && m_bytes[j-1]==' ' ) --j;
|
||||||
if ( i>=j )
|
if ( i>=j )
|
||||||
return Double.NaN;
|
return Double.NaN;
|
||||||
if ( m_bytes[i]=='0' && i+1<j && (m_bytes[i+1]=='x'||m_bytes[i+1]=='X'))
|
int prefix = (m_bytes[i] == '+' || m_bytes[i] == '-') ? i + 1 : i;
|
||||||
return scanlong(16, i+2, j);
|
if (prefix + 1 < j && m_bytes[prefix]=='0' && (m_bytes[prefix+1]=='x'||m_bytes[prefix+1]=='X')) {
|
||||||
|
double l = scanlong(16, prefix + 2, j, i != prefix);
|
||||||
|
return Double.isNaN(l)? scandouble(i,j): l;
|
||||||
|
}
|
||||||
double l = scanlong(10, i, j);
|
double l = scanlong(10, i, j);
|
||||||
return Double.isNaN(l)? scandouble(i,j): l;
|
return Double.isNaN(l)? scandouble(i,j): l;
|
||||||
}
|
}
|
||||||
@@ -796,14 +811,15 @@ public class LuaString extends LuaValue {
|
|||||||
* or Double.NaN if not
|
* or Double.NaN if not
|
||||||
*/
|
*/
|
||||||
private double scanlong( int base, int start, int end ) {
|
private double scanlong( int base, int start, int end ) {
|
||||||
|
return scanlong(base, start, end, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double scanlong( int base, int start, int end, boolean hasSign ) {
|
||||||
long x = 0;
|
long x = 0;
|
||||||
boolean neg = (m_bytes[start] == '-');
|
boolean neg = hasSign && m_bytes[start - 1] == '-';
|
||||||
// --- fix starts here ---
|
if (start >= end)
|
||||||
if(neg && m_bytes.length == 1) {
|
return Double.NaN;
|
||||||
return Double.NaN; // this is only a '-' sign, no parsing any number is required
|
for ( int i=start; i<end; i++ ) {
|
||||||
}
|
|
||||||
// --- fix ends here ---
|
|
||||||
for ( int i=(neg?start+1:start); i<end; i++ ) {
|
|
||||||
int digit = m_bytes[i] - (base<=10||(m_bytes[i]>='0'&&m_bytes[i]<='9')? '0':
|
int digit = m_bytes[i] - (base<=10||(m_bytes[i]>='0'&&m_bytes[i]<='9')? '0':
|
||||||
m_bytes[i]>='A'&&m_bytes[i]<='Z'? ('A'-10): ('a'-10));
|
m_bytes[i]>='A'&&m_bytes[i]<='Z'? ('A'-10): ('a'-10));
|
||||||
if ( digit < 0 || digit >= base )
|
if ( digit < 0 || digit >= base )
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue rawget( LuaValue key ) {
|
public LuaValue rawget( LuaValue key ) {
|
||||||
if ( key.isinttype() ) {
|
if ( key.isint() ) {
|
||||||
int ikey = key.toint();
|
int ikey = key.toint();
|
||||||
if ( ikey>0 && ikey<=array.length ) {
|
if ( ikey>0 && ikey<=array.length ) {
|
||||||
LuaValue v = m_metatable == null
|
LuaValue v = m_metatable == null
|
||||||
@@ -279,7 +279,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
|
|
||||||
/** caller must ensure key is not nil */
|
/** caller must ensure key is not nil */
|
||||||
public void rawset( LuaValue key, LuaValue value ) {
|
public void rawset( LuaValue key, LuaValue value ) {
|
||||||
if ( !key.isinttype() || !arrayset(key.toint(), value) )
|
if ( !key.isint() || !arrayset(key.toint(), value) )
|
||||||
hashset( key, value );
|
hashset( key, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,7 +388,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
do {
|
do {
|
||||||
// find current key index
|
// find current key index
|
||||||
if ( ! key.isnil() ) {
|
if ( ! key.isnil() ) {
|
||||||
if ( key.isinttype() ) {
|
if ( key.isint() ) {
|
||||||
i = key.toint();
|
i = key.toint();
|
||||||
if ( i>0 && i<=array.length ) {
|
if ( i>0 && i<=array.length ) {
|
||||||
break;
|
break;
|
||||||
@@ -473,7 +473,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
if ( checkLoadFactor() ) {
|
if ( checkLoadFactor() ) {
|
||||||
if ( (m_metatable == null || !m_metatable.useWeakValues())
|
if ( (m_metatable == null || !m_metatable.useWeakValues())
|
||||||
&& key.isinttype() && key.toint() > 0 ) {
|
&& key.isint() && key.toint() > 0 ) {
|
||||||
// a rehash might make room in the array portion for this key.
|
// a rehash might make room in the array portion for this key.
|
||||||
rehash( key.toint() );
|
rehash( key.toint() );
|
||||||
if ( arrayset(key.toint(), value) )
|
if ( arrayset(key.toint(), value) )
|
||||||
@@ -767,9 +767,9 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected static Entry defaultEntry(LuaValue key, LuaValue value) {
|
protected static Entry defaultEntry(LuaValue key, LuaValue value) {
|
||||||
if ( key.isinttype() ) {
|
if ( key.isint() ) {
|
||||||
return new IntKeyEntry( key.toint(), value );
|
return new IntKeyEntry( key.toint(), value );
|
||||||
} else if (value.type() == TNUMBER) {
|
} else if (value.type() == TNUMBER && !value.isinttype()) {
|
||||||
return new NumberValueEntry( key, value.todouble() );
|
return new NumberValueEntry( key, value.todouble() );
|
||||||
} else {
|
} else {
|
||||||
return new NormalEntry( key, value );
|
return new NormalEntry( key, value );
|
||||||
|
|||||||
@@ -216,6 +216,24 @@ public class LuaValue extends Varargs {
|
|||||||
/** LuaString constant with value "__idiv" for use as metatag */
|
/** LuaString constant with value "__idiv" for use as metatag */
|
||||||
public static final LuaString IDIV = valueOf("__idiv");
|
public static final LuaString IDIV = valueOf("__idiv");
|
||||||
|
|
||||||
|
/** LuaString constant with value "__band" for use as metatag */
|
||||||
|
public static final LuaString BAND = valueOf("__band");
|
||||||
|
|
||||||
|
/** LuaString constant with value "__bor" for use as metatag */
|
||||||
|
public static final LuaString BOR = valueOf("__bor");
|
||||||
|
|
||||||
|
/** LuaString constant with value "__bxor" for use as metatag */
|
||||||
|
public static final LuaString BXOR = valueOf("__bxor");
|
||||||
|
|
||||||
|
/** LuaString constant with value "__shl" for use as metatag */
|
||||||
|
public static final LuaString SHL = valueOf("__shl");
|
||||||
|
|
||||||
|
/** LuaString constant with value "__shr" for use as metatag */
|
||||||
|
public static final LuaString SHR = valueOf("__shr");
|
||||||
|
|
||||||
|
/** LuaString constant with value "__bnot" for use as metatag */
|
||||||
|
public static final LuaString BNOT = valueOf("__bnot");
|
||||||
|
|
||||||
/** LuaString constant with value "__mul" for use as metatag */
|
/** LuaString constant with value "__mul" for use as metatag */
|
||||||
public static final LuaString MUL = valueOf("__mul");
|
public static final LuaString MUL = valueOf("__mul");
|
||||||
|
|
||||||
@@ -2010,6 +2028,13 @@ public class LuaValue extends Varargs {
|
|||||||
* @throws LuaError if {@code this} is not a table or string, and has no {@link #UNM} metatag
|
* @throws LuaError if {@code this} is not a table or string, and has no {@link #UNM} metatag
|
||||||
*/
|
*/
|
||||||
public LuaValue neg() { return checkmetatag(UNM, "attempt to perform arithmetic on ").call(this); }
|
public LuaValue neg() { return checkmetatag(UNM, "attempt to perform arithmetic on ").call(this); }
|
||||||
|
|
||||||
|
/** Unary bitwise not: return bitwise inverse value {@code (~this)}.
|
||||||
|
* @return numeric inverse as {@link LuaNumber} if integer-coercible,
|
||||||
|
* or metatag processing result if {@link #BNOT} metatag is defined
|
||||||
|
* @throws LuaError if {@code this} cannot be represented as an integer
|
||||||
|
*/
|
||||||
|
public LuaValue bnot() { return checkmetatag(BNOT, "attempt to perform bitwise operation on ").call(this); }
|
||||||
|
|
||||||
/** Length operator: return lua length of object {@code (#this)} including metatag processing as java int
|
/** Length operator: return lua length of object {@code (#this)} including metatag processing as java int
|
||||||
* @return length as defined by the lua # operator
|
* @return length as defined by the lua # operator
|
||||||
@@ -2141,6 +2166,15 @@ public class LuaValue extends Varargs {
|
|||||||
*/
|
*/
|
||||||
public boolean raweq( int val ) { return false; }
|
public boolean raweq( int val ) { return false; }
|
||||||
|
|
||||||
|
/** Equals: Perform direct equality comparison with a long value
|
||||||
|
* without metatag processing.
|
||||||
|
* @param val The long value to compare with.
|
||||||
|
* @return true if {@code this} is a {@link LuaNumber}
|
||||||
|
* whose value equals val,
|
||||||
|
* otherwise false
|
||||||
|
*/
|
||||||
|
public boolean raweq( long val ) { return false; }
|
||||||
|
|
||||||
/** Perform equality testing metatag processing
|
/** Perform equality testing metatag processing
|
||||||
* @param lhs left-hand-side of equality expression
|
* @param lhs left-hand-side of equality expression
|
||||||
* @param lhsmt metatag value for left-hand-side
|
* @param lhsmt metatag value for left-hand-side
|
||||||
@@ -2403,6 +2437,16 @@ public class LuaValue extends Varargs {
|
|||||||
public LuaValue div( LuaValue rhs ) { return arithmt(DIV,rhs); }
|
public LuaValue div( LuaValue rhs ) { return arithmt(DIV,rhs); }
|
||||||
|
|
||||||
public LuaValue idiv( LuaValue rhs ) { return arithmt(IDIV,rhs); }
|
public LuaValue idiv( LuaValue rhs ) { return arithmt(IDIV,rhs); }
|
||||||
|
|
||||||
|
public LuaValue band( LuaValue rhs ) { return arithmt(BAND,rhs); }
|
||||||
|
|
||||||
|
public LuaValue bor( LuaValue rhs ) { return arithmt(BOR,rhs); }
|
||||||
|
|
||||||
|
public LuaValue bxor( LuaValue rhs ) { return arithmt(BXOR,rhs); }
|
||||||
|
|
||||||
|
public LuaValue shl( LuaValue rhs ) { return arithmt(SHL,rhs); }
|
||||||
|
|
||||||
|
public LuaValue shr( LuaValue rhs ) { return arithmt(SHR,rhs); }
|
||||||
|
|
||||||
/** Divide: Perform numeric divide operation by another value
|
/** Divide: Perform numeric divide operation by another value
|
||||||
* of double type without metatag processing
|
* of double type without metatag processing
|
||||||
@@ -2420,6 +2464,16 @@ public class LuaValue extends Varargs {
|
|||||||
public LuaValue div( double rhs ) { return aritherror("div"); }
|
public LuaValue div( double rhs ) { return aritherror("div"); }
|
||||||
|
|
||||||
public LuaValue idiv( double rhs ) { return aritherror("idiv"); }
|
public LuaValue idiv( double rhs ) { return aritherror("idiv"); }
|
||||||
|
|
||||||
|
public LuaValue band( double rhs ) { return aritherror("band"); }
|
||||||
|
|
||||||
|
public LuaValue bor( double rhs ) { return aritherror("bor"); }
|
||||||
|
|
||||||
|
public LuaValue bxor( double rhs ) { return aritherror("bxor"); }
|
||||||
|
|
||||||
|
public LuaValue shl( double rhs ) { return aritherror("shl"); }
|
||||||
|
|
||||||
|
public LuaValue shr( double rhs ) { return aritherror("shr"); }
|
||||||
|
|
||||||
/** Divide: Perform numeric divide operation by another value
|
/** Divide: Perform numeric divide operation by another value
|
||||||
* of int type without metatag processing
|
* of int type without metatag processing
|
||||||
@@ -2437,6 +2491,16 @@ public class LuaValue extends Varargs {
|
|||||||
public LuaValue div( int rhs ) { return aritherror("div"); }
|
public LuaValue div( int rhs ) { return aritherror("div"); }
|
||||||
|
|
||||||
public LuaValue idiv( int rhs ) { return aritherror("idiv"); }
|
public LuaValue idiv( int rhs ) { return aritherror("idiv"); }
|
||||||
|
|
||||||
|
public LuaValue band( int rhs ) { return aritherror("band"); }
|
||||||
|
|
||||||
|
public LuaValue bor( int rhs ) { return aritherror("bor"); }
|
||||||
|
|
||||||
|
public LuaValue bxor( int rhs ) { return aritherror("bxor"); }
|
||||||
|
|
||||||
|
public LuaValue shl( int rhs ) { return aritherror("shl"); }
|
||||||
|
|
||||||
|
public LuaValue shr( int rhs ) { return aritherror("shr"); }
|
||||||
|
|
||||||
/** Reverse-divide: Perform numeric divide operation into another value
|
/** Reverse-divide: Perform numeric divide operation into another value
|
||||||
* with metatag processing
|
* with metatag processing
|
||||||
@@ -2454,6 +2518,16 @@ public class LuaValue extends Varargs {
|
|||||||
public LuaValue divInto(double lhs) { return arithmtwith(DIV,lhs); }
|
public LuaValue divInto(double lhs) { return arithmtwith(DIV,lhs); }
|
||||||
|
|
||||||
public LuaValue idivInto(double lhs) { return arithmtwith(IDIV,lhs); }
|
public LuaValue idivInto(double lhs) { return arithmtwith(IDIV,lhs); }
|
||||||
|
|
||||||
|
public LuaValue bandInto(double lhs) { return arithmtwith(BAND,lhs); }
|
||||||
|
|
||||||
|
public LuaValue borInto(double lhs) { return arithmtwith(BOR,lhs); }
|
||||||
|
|
||||||
|
public LuaValue bxorInto(double lhs) { return arithmtwith(BXOR,lhs); }
|
||||||
|
|
||||||
|
public LuaValue shlInto(double lhs) { return arithmtwith(SHL,lhs); }
|
||||||
|
|
||||||
|
public LuaValue shrInto(double lhs) { return arithmtwith(SHR,lhs); }
|
||||||
|
|
||||||
/** Modulo: Perform numeric modulo operation with another value
|
/** Modulo: Perform numeric modulo operation with another value
|
||||||
* of unknown type,
|
* of unknown type,
|
||||||
@@ -3173,6 +3247,13 @@ public class LuaValue extends Varargs {
|
|||||||
* @return {@link LuaInteger} instance, possibly pooled, whose value is i
|
* @return {@link LuaInteger} instance, possibly pooled, whose value is i
|
||||||
*/
|
*/
|
||||||
public static LuaInteger valueOf(int i) { return LuaInteger.valueOf(i); }
|
public static LuaInteger valueOf(int i) { return LuaInteger.valueOf(i); }
|
||||||
|
|
||||||
|
/** Convert java long to a {@link LuaValue}.
|
||||||
|
*
|
||||||
|
* @param l long value to convert
|
||||||
|
* @return {@link LuaInteger} instance, possibly pooled, whose value is l
|
||||||
|
*/
|
||||||
|
public static LuaInteger valueOf(long l) { return LuaInteger.valueOf(l); }
|
||||||
|
|
||||||
/** Convert java double to a {@link LuaValue}.
|
/** Convert java double to a {@link LuaValue}.
|
||||||
* This may return a {@link LuaInteger} or {@link LuaDouble} depending
|
* This may return a {@link LuaInteger} or {@link LuaDouble} depending
|
||||||
|
|||||||
@@ -277,6 +277,11 @@ public class Print extends Lua {
|
|||||||
case OP_MUL:
|
case OP_MUL:
|
||||||
case OP_DIV:
|
case OP_DIV:
|
||||||
case OP_IDIV:
|
case OP_IDIV:
|
||||||
|
case OP_BAND:
|
||||||
|
case OP_BOR:
|
||||||
|
case OP_BXOR:
|
||||||
|
case OP_SHL:
|
||||||
|
case OP_SHR:
|
||||||
case OP_POW:
|
case OP_POW:
|
||||||
case OP_EQ:
|
case OP_EQ:
|
||||||
case OP_LT:
|
case OP_LT:
|
||||||
|
|||||||
@@ -890,6 +890,21 @@ public class FuncState extends Constants {
|
|||||||
case OP_IDIV:
|
case OP_IDIV:
|
||||||
r = v1.idiv(v2);
|
r = v1.idiv(v2);
|
||||||
break;
|
break;
|
||||||
|
case OP_BAND:
|
||||||
|
r = v1.band(v2);
|
||||||
|
break;
|
||||||
|
case OP_BOR:
|
||||||
|
r = v1.bor(v2);
|
||||||
|
break;
|
||||||
|
case OP_BXOR:
|
||||||
|
r = v1.bxor(v2);
|
||||||
|
break;
|
||||||
|
case OP_SHL:
|
||||||
|
r = v1.shl(v2);
|
||||||
|
break;
|
||||||
|
case OP_SHR:
|
||||||
|
r = v1.shr(v2);
|
||||||
|
break;
|
||||||
case OP_MOD:
|
case OP_MOD:
|
||||||
r = v1.mod(v2);
|
r = v1.mod(v2);
|
||||||
break;
|
break;
|
||||||
@@ -899,6 +914,9 @@ public class FuncState extends Constants {
|
|||||||
case OP_UNM:
|
case OP_UNM:
|
||||||
r = v1.neg();
|
r = v1.neg();
|
||||||
break;
|
break;
|
||||||
|
case OP_BNOT:
|
||||||
|
r = v1.bnot();
|
||||||
|
break;
|
||||||
case OP_LEN:
|
case OP_LEN:
|
||||||
// r = v1.len();
|
// r = v1.len();
|
||||||
// break;
|
// break;
|
||||||
@@ -918,7 +936,7 @@ public class FuncState extends Constants {
|
|||||||
if (constfolding(op, e1, e2))
|
if (constfolding(op, e1, e2))
|
||||||
return;
|
return;
|
||||||
else {
|
else {
|
||||||
int o2 = (op != OP_UNM && op != OP_LEN) ? this.exp2RK(e2)
|
int o2 = (op != OP_UNM && op != OP_BNOT && op != OP_LEN) ? this.exp2RK(e2)
|
||||||
: 0;
|
: 0;
|
||||||
int o1 = this.exp2RK(e1);
|
int o1 = this.exp2RK(e1);
|
||||||
if (o1 > o2) {
|
if (o1 > o2) {
|
||||||
@@ -971,6 +989,15 @@ public class FuncState extends Constants {
|
|||||||
this.codearith(OP_LEN, e, e2, line);
|
this.codearith(OP_LEN, e, e2, line);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case LexState.OPR_BNOT: {
|
||||||
|
if (e.isnumeral())
|
||||||
|
e.u.setNval(e.u.nval().bnot());
|
||||||
|
else {
|
||||||
|
this.exp2anyreg(e);
|
||||||
|
this.codearith(OP_BNOT, e, e2, line);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
_assert (false);
|
_assert (false);
|
||||||
}
|
}
|
||||||
@@ -995,6 +1022,11 @@ public class FuncState extends Constants {
|
|||||||
case LexState.OPR_MUL:
|
case LexState.OPR_MUL:
|
||||||
case LexState.OPR_DIV:
|
case LexState.OPR_DIV:
|
||||||
case LexState.OPR_IDIV:
|
case LexState.OPR_IDIV:
|
||||||
|
case LexState.OPR_BAND:
|
||||||
|
case LexState.OPR_BOR:
|
||||||
|
case LexState.OPR_BXOR:
|
||||||
|
case LexState.OPR_SHL:
|
||||||
|
case LexState.OPR_SHR:
|
||||||
case LexState.OPR_MOD:
|
case LexState.OPR_MOD:
|
||||||
case LexState.OPR_POW: {
|
case LexState.OPR_POW: {
|
||||||
if (!v.isnumeral())
|
if (!v.isnumeral())
|
||||||
@@ -1057,6 +1089,21 @@ public class FuncState extends Constants {
|
|||||||
case LexState.OPR_IDIV:
|
case LexState.OPR_IDIV:
|
||||||
this.codearith(OP_IDIV, e1, e2, line);
|
this.codearith(OP_IDIV, e1, e2, line);
|
||||||
break;
|
break;
|
||||||
|
case LexState.OPR_BAND:
|
||||||
|
this.codearith(OP_BAND, e1, e2, line);
|
||||||
|
break;
|
||||||
|
case LexState.OPR_BOR:
|
||||||
|
this.codearith(OP_BOR, e1, e2, line);
|
||||||
|
break;
|
||||||
|
case LexState.OPR_BXOR:
|
||||||
|
this.codearith(OP_BXOR, e1, e2, line);
|
||||||
|
break;
|
||||||
|
case LexState.OPR_SHL:
|
||||||
|
this.codearith(OP_SHL, e1, e2, line);
|
||||||
|
break;
|
||||||
|
case LexState.OPR_SHR:
|
||||||
|
this.codearith(OP_SHR, e1, e2, line);
|
||||||
|
break;
|
||||||
case LexState.OPR_MOD:
|
case LexState.OPR_MOD:
|
||||||
this.codearith(OP_MOD, e1, e2, line);
|
this.codearith(OP_MOD, e1, e2, line);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -85,15 +85,16 @@ 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_IDIV=4, OPR_MOD=5, OPR_POW=6,
|
OPR_ADD=0, OPR_SUB=1, OPR_MUL=2, OPR_DIV=3, OPR_IDIV=4, OPR_BAND=5, OPR_BOR=6,
|
||||||
OPR_CONCAT=7,
|
OPR_BXOR=7, OPR_SHL=8, OPR_SHR=9, OPR_MOD=10, OPR_POW=11,
|
||||||
OPR_NE=8, OPR_EQ=9,
|
OPR_CONCAT=12,
|
||||||
OPR_LT=10, OPR_LE=11, OPR_GT=12, OPR_GE=13,
|
OPR_NE=13, OPR_EQ=14,
|
||||||
OPR_AND=14, OPR_OR=15,
|
OPR_LT=15, OPR_LE=16, OPR_GT=17, OPR_GE=18,
|
||||||
OPR_NOBINOPR=16;
|
OPR_AND=19, OPR_OR=20,
|
||||||
|
OPR_NOBINOPR=21;
|
||||||
|
|
||||||
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_BNOT=3, OPR_NOUNOPR=4;
|
||||||
|
|
||||||
/* exp kind */
|
/* exp kind */
|
||||||
static final int
|
static final int
|
||||||
@@ -149,7 +150,7 @@ public class LexState extends Constants {
|
|||||||
"end", "false", "for", "function", "goto", "if",
|
"end", "false", "for", "function", "goto", "if",
|
||||||
"in", "local", "nil", "not", "or", "repeat",
|
"in", "local", "nil", "not", "or", "repeat",
|
||||||
"return", "then", "true", "until", "while",
|
"return", "then", "true", "until", "while",
|
||||||
"..", "...", "//", "==", ">=", "<=", "~=",
|
"..", "...", "//", "<<", ">>", "==", ">=", "<=", "~=",
|
||||||
"::", "<eos>", "<number>", "<name>", "<string>", "<eof>",
|
"::", "<eos>", "<number>", "<name>", "<string>", "<eof>",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -160,8 +161,8 @@ public class LexState extends Constants {
|
|||||||
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_IDIV=281, TK_EQ=282, TK_GE=283, TK_LE=284, TK_NE=285,
|
TK_CONCAT=279, TK_DOTS=280, TK_IDIV=281, TK_SHL=282, TK_SHR=283, TK_EQ=284, TK_GE=285, TK_LE=286, TK_NE=287,
|
||||||
TK_DBCOLON=286, TK_EOS=287, TK_NUMBER=288, TK_NAME=289, TK_STRING=290;
|
TK_DBCOLON=288, TK_EOS=289, TK_NUMBER=290, TK_NAME=291, TK_STRING=292;
|
||||||
|
|
||||||
final static int FIRST_RESERVED = TK_AND;
|
final static int FIRST_RESERVED = TK_AND;
|
||||||
final static int NUM_RESERVED = TK_WHILE+1-FIRST_RESERVED;
|
final static int NUM_RESERVED = TK_WHILE+1-FIRST_RESERVED;
|
||||||
@@ -335,52 +336,27 @@ public class LexState extends Constants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LuaValue strx2number(String str, SemInfo seminfo) {
|
LuaValue strx2number(String str, SemInfo seminfo) {
|
||||||
char[] c = str.toCharArray();
|
String trimmed = str.trim();
|
||||||
int s = 0;
|
try {
|
||||||
while ( s < c.length && isspace(c[s]))
|
if (trimmed.indexOf('.') < 0 && trimmed.indexOf('p') < 0 && trimmed.indexOf('P') < 0) {
|
||||||
++s;
|
boolean negative = trimmed.startsWith("-");
|
||||||
// Check for negative sign
|
boolean positive = trimmed.startsWith("+");
|
||||||
double sgn = 1.0;
|
int prefix = negative || positive ? 3 : 2;
|
||||||
if (s < c.length && c[s] == '-') {
|
String digits = trimmed.substring(prefix);
|
||||||
sgn = -1.0;
|
long value = Long.parseUnsignedLong(digits, 16);
|
||||||
++s;
|
if (negative) {
|
||||||
}
|
if (value == Long.MIN_VALUE) {
|
||||||
/* Check for "0x" */
|
return LuaValue.valueOf(Long.MIN_VALUE);
|
||||||
if (s + 2 >= c.length )
|
}
|
||||||
return LuaValue.ZERO;
|
return LuaValue.valueOf(-value);
|
||||||
if (c[s++] != '0')
|
}
|
||||||
return LuaValue.ZERO;
|
return LuaValue.valueOf(value);
|
||||||
if (c[s] != 'x' && c[s] != 'X')
|
|
||||||
return LuaValue.ZERO;
|
|
||||||
++s;
|
|
||||||
|
|
||||||
// read integer part.
|
|
||||||
double m = 0;
|
|
||||||
int e = 0;
|
|
||||||
while (s < c.length && isxdigit(c[s]))
|
|
||||||
m = (m * 16) + hexvalue(c[s++]);
|
|
||||||
if (s < c.length && c[s] == '.') {
|
|
||||||
++s; // skip dot
|
|
||||||
while (s < c.length && isxdigit(c[s])) {
|
|
||||||
m = (m * 16) + hexvalue(c[s++]);
|
|
||||||
e -= 4; // Each fractional part shifts right by 2^4
|
|
||||||
}
|
}
|
||||||
|
return LuaValue.valueOf(Double.parseDouble(trimmed));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
lexerror("malformed number (" + e.getMessage() + ")", TK_NUMBER);
|
||||||
|
return LuaValue.NIL;
|
||||||
}
|
}
|
||||||
if (s < c.length && (c[s] == 'p' || c[s] == 'P')) {
|
|
||||||
++s;
|
|
||||||
int exp1 = 0;
|
|
||||||
boolean neg1 = false;
|
|
||||||
if (s < c.length && c[s] == '-') {
|
|
||||||
neg1 = true;
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
while (s < c.length && isdigit(c[s]))
|
|
||||||
exp1 = exp1 * 10 + c[s++] - '0';
|
|
||||||
if (neg1)
|
|
||||||
exp1 = -exp1;
|
|
||||||
e += exp1;
|
|
||||||
}
|
|
||||||
return LuaValue.valueOf(sgn * m * MathLib.dpow_d(2.0, e));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean str2d(String str, SemInfo seminfo) {
|
boolean str2d(String str, SemInfo seminfo) {
|
||||||
@@ -390,7 +366,12 @@ public class LexState extends Constants {
|
|||||||
seminfo.r = strx2number(str, seminfo);
|
seminfo.r = strx2number(str, seminfo);
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
seminfo.r = LuaValue.valueOf(Double.parseDouble(str.trim()));
|
String trimmed = str.trim();
|
||||||
|
if (trimmed.indexOf('.') < 0 && trimmed.indexOf('e') < 0 && trimmed.indexOf('E') < 0) {
|
||||||
|
seminfo.r = LuaValue.valueOf(Long.parseLong(trimmed));
|
||||||
|
} else {
|
||||||
|
seminfo.r = LuaValue.valueOf(Double.parseDouble(trimmed));
|
||||||
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
lexerror("malformed number (" + e.getMessage() + ")", TK_NUMBER);
|
lexerror("malformed number (" + e.getMessage() + ")", TK_NUMBER);
|
||||||
}
|
}
|
||||||
@@ -640,7 +621,10 @@ public class LexState extends Constants {
|
|||||||
}
|
}
|
||||||
case '<': {
|
case '<': {
|
||||||
nextChar();
|
nextChar();
|
||||||
if (current != '=')
|
if (current == '<') {
|
||||||
|
nextChar();
|
||||||
|
return TK_SHL;
|
||||||
|
} else if (current != '=')
|
||||||
return '<';
|
return '<';
|
||||||
else {
|
else {
|
||||||
nextChar();
|
nextChar();
|
||||||
@@ -649,7 +633,10 @@ public class LexState extends Constants {
|
|||||||
}
|
}
|
||||||
case '>': {
|
case '>': {
|
||||||
nextChar();
|
nextChar();
|
||||||
if (current != '=')
|
if (current == '>') {
|
||||||
|
nextChar();
|
||||||
|
return TK_SHR;
|
||||||
|
} else if (current != '=')
|
||||||
return '>';
|
return '>';
|
||||||
else {
|
else {
|
||||||
nextChar();
|
nextChar();
|
||||||
@@ -1510,6 +1497,8 @@ public class LexState extends Constants {
|
|||||||
return OPR_MINUS;
|
return OPR_MINUS;
|
||||||
case '#':
|
case '#':
|
||||||
return OPR_LEN;
|
return OPR_LEN;
|
||||||
|
case '~':
|
||||||
|
return OPR_BNOT;
|
||||||
default:
|
default:
|
||||||
return OPR_NOUNOPR;
|
return OPR_NOUNOPR;
|
||||||
}
|
}
|
||||||
@@ -1528,6 +1517,16 @@ public class LexState extends Constants {
|
|||||||
return OPR_DIV;
|
return OPR_DIV;
|
||||||
case TK_IDIV:
|
case TK_IDIV:
|
||||||
return OPR_IDIV;
|
return OPR_IDIV;
|
||||||
|
case '&':
|
||||||
|
return OPR_BAND;
|
||||||
|
case '|':
|
||||||
|
return OPR_BOR;
|
||||||
|
case '~':
|
||||||
|
return OPR_BXOR;
|
||||||
|
case TK_SHL:
|
||||||
|
return OPR_SHL;
|
||||||
|
case TK_SHR:
|
||||||
|
return OPR_SHR;
|
||||||
case '%':
|
case '%':
|
||||||
return OPR_MOD;
|
return OPR_MOD;
|
||||||
case '^':
|
case '^':
|
||||||
@@ -1567,14 +1566,15 @@ public class LexState extends Constants {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static Priority[] priority = { /* ORDER OPR */
|
static Priority[] priority = { /* ORDER OPR */
|
||||||
new Priority(6, 6), new Priority(6, 6), new Priority(7, 7), new Priority(7, 7), new Priority(7, 7), new Priority(7, 7), /* `+' `-' `*' `/' `//' `%' */
|
new Priority(10, 10), new Priority(10, 10), new Priority(11, 11), new Priority(11, 11), new Priority(11, 11), new Priority(6, 6), new Priority(4, 4),
|
||||||
new Priority(10, 9), new Priority(5, 4), /* power and concat (right associative) */
|
new Priority(5, 5), new Priority(7, 7), new Priority(7, 7), new Priority(11, 11), new Priority(13, 12),
|
||||||
new Priority(3, 3), new Priority(3, 3), /* equality and inequality */
|
new Priority(8, 7),
|
||||||
new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), /* order */
|
new Priority(3, 3), new Priority(3, 3),
|
||||||
new Priority(2, 2), new Priority(1, 1) /* logical (and/or) */
|
new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), new Priority(3, 3),
|
||||||
|
new Priority(2, 2), new Priority(1, 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
static final int UNARY_PRIORITY = 8; /* priority for unary operators */
|
static final int UNARY_PRIORITY = 12; /* priority for unary operators */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ public class CoroutineLib extends TwoArgFunction {
|
|||||||
globals = env.checkglobals();
|
globals = env.checkglobals();
|
||||||
LuaTable coroutine = new LuaTable();
|
LuaTable coroutine = new LuaTable();
|
||||||
coroutine.set("create", new Create());
|
coroutine.set("create", new Create());
|
||||||
|
coroutine.set("isyieldable", new IsYieldable());
|
||||||
coroutine.set("resume", new Resume());
|
coroutine.set("resume", new Resume());
|
||||||
coroutine.set("running", new Running());
|
coroutine.set("running", new Running());
|
||||||
coroutine.set("status", new Status());
|
coroutine.set("status", new Status());
|
||||||
@@ -99,6 +100,13 @@ public class CoroutineLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final class IsYieldable extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
final LuaThread r = globals.running;
|
||||||
|
return valueOf(r != null && !r.isMainThread());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final class Running extends VarArgFunction {
|
final class Running extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
final LuaThread r = globals.running;
|
final LuaThread r = globals.running;
|
||||||
@@ -141,4 +149,4 @@ public class CoroutineLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -817,9 +817,15 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
case Lua.OP_MUL: tm = LuaValue.MUL; break;
|
case Lua.OP_MUL: tm = LuaValue.MUL; break;
|
||||||
case Lua.OP_DIV: tm = LuaValue.DIV; break;
|
case Lua.OP_DIV: tm = LuaValue.DIV; break;
|
||||||
case Lua.OP_IDIV: tm = LuaValue.IDIV; break;
|
case Lua.OP_IDIV: tm = LuaValue.IDIV; break;
|
||||||
|
case Lua.OP_BAND: tm = LuaValue.BAND; break;
|
||||||
|
case Lua.OP_BOR: tm = LuaValue.BOR; break;
|
||||||
|
case Lua.OP_BXOR: tm = LuaValue.BXOR; break;
|
||||||
|
case Lua.OP_SHL: tm = LuaValue.SHL; break;
|
||||||
|
case Lua.OP_SHR: tm = LuaValue.SHR; break;
|
||||||
case Lua.OP_MOD: tm = LuaValue.MOD; break;
|
case Lua.OP_MOD: tm = LuaValue.MOD; break;
|
||||||
case Lua.OP_POW: tm = LuaValue.POW; break;
|
case Lua.OP_POW: tm = LuaValue.POW; break;
|
||||||
case Lua.OP_UNM: tm = LuaValue.UNM; break;
|
case Lua.OP_UNM: tm = LuaValue.UNM; break;
|
||||||
|
case Lua.OP_BNOT: tm = LuaValue.BNOT; break;
|
||||||
case Lua.OP_LEN: tm = LuaValue.LEN; break;
|
case Lua.OP_LEN: tm = LuaValue.LEN; break;
|
||||||
case Lua.OP_LT: tm = LuaValue.LT; break;
|
case Lua.OP_LT: tm = LuaValue.LT; break;
|
||||||
case Lua.OP_LE: tm = LuaValue.LE; break;
|
case Lua.OP_LE: tm = LuaValue.LE; break;
|
||||||
|
|||||||
@@ -113,7 +113,9 @@ public class MathLib extends TwoArgFunction {
|
|||||||
math.set("huge", LuaDouble.POSINF );
|
math.set("huge", LuaDouble.POSINF );
|
||||||
math.set("ldexp", new ldexp());
|
math.set("ldexp", new ldexp());
|
||||||
math.set("max", new max());
|
math.set("max", new max());
|
||||||
|
math.set("maxinteger", LuaValue.valueOf(Long.MAX_VALUE));
|
||||||
math.set("min", new min());
|
math.set("min", new min());
|
||||||
|
math.set("mininteger", LuaValue.valueOf(Long.MIN_VALUE));
|
||||||
math.set("modf", new modf());
|
math.set("modf", new modf());
|
||||||
math.set("pi", Math.PI );
|
math.set("pi", Math.PI );
|
||||||
math.set("pow", new pow());
|
math.set("pow", new pow());
|
||||||
@@ -124,6 +126,9 @@ public class MathLib extends TwoArgFunction {
|
|||||||
math.set("sin", new sin());
|
math.set("sin", new sin());
|
||||||
math.set("sqrt", new sqrt());
|
math.set("sqrt", new sqrt());
|
||||||
math.set("tan", new tan());
|
math.set("tan", new tan());
|
||||||
|
math.set("tointeger", new tointeger());
|
||||||
|
math.set("type", new type());
|
||||||
|
math.set("ult", new ult());
|
||||||
env.set("math", math);
|
env.set("math", math);
|
||||||
if (!env.get("package").isnil()) env.get("package").get("loaded").set("math", math);
|
if (!env.get("package").isnil()) env.get("package").get("loaded").set("math", math);
|
||||||
return math;
|
return math;
|
||||||
@@ -229,6 +234,34 @@ public class MathLib extends TwoArgFunction {
|
|||||||
return varargsOf( valueOf(intPart), valueOf(fracPart) );
|
return varargsOf( valueOf(intPart), valueOf(fracPart) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class tointeger extends OneArgFunction {
|
||||||
|
public LuaValue call(LuaValue arg) {
|
||||||
|
LuaValue n = arg.tonumber();
|
||||||
|
if (n.isnil() || !n.islong()) {
|
||||||
|
return NIL;
|
||||||
|
}
|
||||||
|
return LuaValue.valueOf(n.tolong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class type extends OneArgFunction {
|
||||||
|
public LuaValue call(LuaValue arg) {
|
||||||
|
LuaValue n = arg.tonumber();
|
||||||
|
if (n.isnil()) {
|
||||||
|
return NIL;
|
||||||
|
}
|
||||||
|
return LuaValue.valueOf(n.isinttype()? "integer": "float");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ult extends TwoArgFunction {
|
||||||
|
public LuaValue call(LuaValue x, LuaValue y) {
|
||||||
|
long a = x.checklong();
|
||||||
|
long b = y.checklong();
|
||||||
|
return valueOf(Long.compareUnsigned(a, b) < 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static class random extends LibFunction {
|
static class random extends LibFunction {
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
@@ -236,17 +269,28 @@ public class MathLib extends TwoArgFunction {
|
|||||||
return valueOf( random.nextDouble() );
|
return valueOf( random.nextDouble() );
|
||||||
}
|
}
|
||||||
public LuaValue call(LuaValue a) {
|
public LuaValue call(LuaValue a) {
|
||||||
int m = a.checkint();
|
long upper = a.checklong();
|
||||||
if (m<1) argerror(1, "interval is empty");
|
if (upper < 1) argerror(1, "interval is empty");
|
||||||
return valueOf( 1 + random.nextInt(m) );
|
return valueOf(nextLong(1, upper));
|
||||||
}
|
}
|
||||||
public LuaValue call(LuaValue a, LuaValue b) {
|
public LuaValue call(LuaValue a, LuaValue b) {
|
||||||
int m = a.checkint();
|
long lower = a.checklong();
|
||||||
int n = b.checkint();
|
long upper = b.checklong();
|
||||||
if (n<m) argerror(2, "interval is empty");
|
if (upper < lower) argerror(2, "interval is empty");
|
||||||
return valueOf( m + random.nextInt(n+1-m) );
|
return valueOf(nextLong(lower, upper));
|
||||||
|
}
|
||||||
|
|
||||||
|
private long nextLong(long lower, long upper) {
|
||||||
|
long bound = upper - lower + 1;
|
||||||
|
if (bound <= 0) {
|
||||||
|
long value;
|
||||||
|
do {
|
||||||
|
value = random.nextLong();
|
||||||
|
} while (Long.compareUnsigned(value - lower, upper - lower) > 0);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return lower + random.nextLong(bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class randomseed extends OneArgFunction {
|
static class randomseed extends OneArgFunction {
|
||||||
|
|||||||
@@ -23,9 +23,11 @@ package org.luaj.vm2.libs;
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
|
||||||
import org.luaj.vm2.Buffer;
|
import org.luaj.vm2.Buffer;
|
||||||
import org.luaj.vm2.LuaClosure;
|
import org.luaj.vm2.LuaClosure;
|
||||||
|
import org.luaj.vm2.LuaError;
|
||||||
import org.luaj.vm2.LuaString;
|
import org.luaj.vm2.LuaString;
|
||||||
import org.luaj.vm2.LuaTable;
|
import org.luaj.vm2.LuaTable;
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
@@ -93,9 +95,12 @@ public class StringLib extends TwoArgFunction {
|
|||||||
string.set("len", new len());
|
string.set("len", new len());
|
||||||
string.set("lower", new lower());
|
string.set("lower", new lower());
|
||||||
string.set("match", new match());
|
string.set("match", new match());
|
||||||
|
string.set("pack", new pack());
|
||||||
|
string.set("packsize", new packsize());
|
||||||
string.set("rep", new rep());
|
string.set("rep", new rep());
|
||||||
string.set("reverse", new reverse());
|
string.set("reverse", new reverse());
|
||||||
string.set("sub", new sub());
|
string.set("sub", new sub());
|
||||||
|
string.set("unpack", new unpack());
|
||||||
string.set("upper", new upper());
|
string.set("upper", new upper());
|
||||||
|
|
||||||
env.set("string", string);
|
env.set("string", string);
|
||||||
@@ -327,6 +332,149 @@ public class StringLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
buf.append( (byte) '"' );
|
buf.append( (byte) '"' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final class pack extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
FormatState state = new FormatState(args.checkstring(1));
|
||||||
|
ByteArrayOutput out = new ByteArrayOutput();
|
||||||
|
int arg = 2;
|
||||||
|
while (state.hasMore()) {
|
||||||
|
FormatOption option = state.next();
|
||||||
|
int padding = state.alignmentPadding(out.size(), option);
|
||||||
|
out.pad(padding);
|
||||||
|
switch (option.kind) {
|
||||||
|
case PADDING:
|
||||||
|
out.pad(option.size);
|
||||||
|
break;
|
||||||
|
case ALIGN:
|
||||||
|
out.pad(option.size);
|
||||||
|
break;
|
||||||
|
case SIGNED:
|
||||||
|
writeInteger(out, args.checklong(arg++), option.size, state.littleEndian, true);
|
||||||
|
break;
|
||||||
|
case UNSIGNED:
|
||||||
|
writeInteger(out, checkUnsigned(args.checklong(arg++), option.size), option.size, state.littleEndian, false);
|
||||||
|
break;
|
||||||
|
case FLOAT:
|
||||||
|
writeFloat(out, (float) args.checkdouble(arg++), state.littleEndian);
|
||||||
|
break;
|
||||||
|
case DOUBLE:
|
||||||
|
writeDouble(out, args.checkdouble(arg++), state.littleEndian);
|
||||||
|
break;
|
||||||
|
case FIXED_STRING: {
|
||||||
|
LuaString s = args.checkstring(arg++);
|
||||||
|
if (s.rawlen() > option.size) {
|
||||||
|
argerror(arg - 1, "string longer than given size");
|
||||||
|
}
|
||||||
|
out.write(s);
|
||||||
|
out.pad(option.size - s.rawlen());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ZERO_STRING: {
|
||||||
|
LuaString s = args.checkstring(arg++);
|
||||||
|
for (int i = 0; i < s.rawlen(); i++) {
|
||||||
|
if (s.luaByte(i) == 0) {
|
||||||
|
argerror(arg - 1, "string contains zeros");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.write(s);
|
||||||
|
out.writeByte(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SIZED_STRING: {
|
||||||
|
LuaString s = args.checkstring(arg++);
|
||||||
|
writeInteger(out, checkUnsigned(s.rawlen(), option.size), option.size, state.littleEndian, false);
|
||||||
|
out.write(s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new LuaError("unsupported pack option");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LuaString.valueUsing(out.toByteArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class packsize extends OneArgFunction {
|
||||||
|
public LuaValue call(LuaValue arg) {
|
||||||
|
FormatState state = new FormatState(arg.checkstring());
|
||||||
|
int offset = 0;
|
||||||
|
while (state.hasMore()) {
|
||||||
|
FormatOption option = state.next();
|
||||||
|
offset += state.alignmentPadding(offset, option);
|
||||||
|
if (option.kind == OptionKind.ZERO_STRING || option.kind == OptionKind.SIZED_STRING) {
|
||||||
|
throw new LuaError("variable-length format");
|
||||||
|
}
|
||||||
|
offset += option.size;
|
||||||
|
}
|
||||||
|
return valueOf(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class unpack extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
FormatState state = new FormatState(args.checkstring(1));
|
||||||
|
LuaString input = args.checkstring(2);
|
||||||
|
int position = posrelat(args.optint(3, 1), input.rawlen());
|
||||||
|
if (position < 1) {
|
||||||
|
position = 1;
|
||||||
|
}
|
||||||
|
int offset = position - 1;
|
||||||
|
java.util.ArrayList<LuaValue> values = new java.util.ArrayList<LuaValue>();
|
||||||
|
while (state.hasMore()) {
|
||||||
|
FormatOption option = state.next();
|
||||||
|
offset += state.alignmentPadding(offset, option);
|
||||||
|
requireBytes(input, offset, option.kind == OptionKind.ZERO_STRING ? 1 : option.size);
|
||||||
|
switch (option.kind) {
|
||||||
|
case PADDING:
|
||||||
|
case ALIGN:
|
||||||
|
offset += option.size;
|
||||||
|
break;
|
||||||
|
case SIGNED:
|
||||||
|
values.add(LuaValue.valueOf(readInteger(input, offset, option.size, state.littleEndian, true)));
|
||||||
|
offset += option.size;
|
||||||
|
break;
|
||||||
|
case UNSIGNED:
|
||||||
|
values.add(LuaValue.valueOf(readUnsignedInteger(input, offset, option.size, state.littleEndian)));
|
||||||
|
offset += option.size;
|
||||||
|
break;
|
||||||
|
case FLOAT:
|
||||||
|
values.add(LuaValue.valueOf(readFloat(input, offset, state.littleEndian)));
|
||||||
|
offset += option.size;
|
||||||
|
break;
|
||||||
|
case DOUBLE:
|
||||||
|
values.add(LuaValue.valueOf(readDouble(input, offset, state.littleEndian)));
|
||||||
|
offset += option.size;
|
||||||
|
break;
|
||||||
|
case FIXED_STRING:
|
||||||
|
values.add(input.substring(offset, offset + option.size));
|
||||||
|
offset += option.size;
|
||||||
|
break;
|
||||||
|
case ZERO_STRING: {
|
||||||
|
int end = findZero(input, offset);
|
||||||
|
values.add(input.substring(offset, end));
|
||||||
|
offset = end + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SIZED_STRING: {
|
||||||
|
long len = readUnsignedInteger(input, offset, option.size, state.littleEndian);
|
||||||
|
offset += option.size;
|
||||||
|
if (len > Integer.MAX_VALUE) {
|
||||||
|
throw new LuaError("string length does not fit");
|
||||||
|
}
|
||||||
|
requireBytes(input, offset, (int) len);
|
||||||
|
values.add(input.substring(offset, offset + (int) len));
|
||||||
|
offset += (int) len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new LuaError("unsupported unpack option");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
values.add(LuaValue.valueOf(offset + 1));
|
||||||
|
return LuaValue.varargsOf(values.toArray(new LuaValue[values.size()]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static final String FLAGS = "-+ #0";
|
private static final String FLAGS = "-+ #0";
|
||||||
|
|
||||||
@@ -745,6 +893,371 @@ public class StringLib extends TwoArgFunction {
|
|||||||
return valueOf(arg.checkjstring().toUpperCase());
|
return valueOf(arg.checkjstring().toUpperCase());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void requireBytes(LuaString input, int offset, int size) {
|
||||||
|
if (offset < 0 || offset + size > input.rawlen()) {
|
||||||
|
throw new LuaError("data string too short");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int findZero(LuaString input, int offset) {
|
||||||
|
for (int i = offset, n = input.rawlen(); i < n; i++) {
|
||||||
|
if (input.luaByte(i) == 0) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new LuaError("unfinished string for format 'z'");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long checkUnsigned(long value, int size) {
|
||||||
|
if (value < 0) {
|
||||||
|
throw new LuaError("unsigned overflow");
|
||||||
|
}
|
||||||
|
if (size < 8 && value >= (1L << (size * 8))) {
|
||||||
|
throw new LuaError("unsigned overflow");
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void writeInteger(ByteArrayOutput out, long value, int size, boolean littleEndian, boolean signed) {
|
||||||
|
if (size <= 0 || size > 16) {
|
||||||
|
throw new LuaError("integral size out of limits");
|
||||||
|
}
|
||||||
|
byte fill = (byte) ((signed && value < 0) ? 0xFF : 0x00);
|
||||||
|
byte[] bytes = new byte[size];
|
||||||
|
long v = value;
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
int index = littleEndian ? i : (size - 1 - i);
|
||||||
|
if (i < 8) {
|
||||||
|
bytes[index] = (byte) (v & 0xFF);
|
||||||
|
v >>= 8;
|
||||||
|
} else {
|
||||||
|
bytes[index] = fill;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.write(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long readInteger(LuaString input, int offset, int size, boolean littleEndian, boolean signed) {
|
||||||
|
if (!signed) {
|
||||||
|
return readUnsignedInteger(input, offset, size, littleEndian);
|
||||||
|
}
|
||||||
|
if (size <= 0 || size > 16) {
|
||||||
|
throw new LuaError("integral size out of limits");
|
||||||
|
}
|
||||||
|
requireBytes(input, offset, size);
|
||||||
|
long result = 0L;
|
||||||
|
int bytesToRead = Math.min(size, 8);
|
||||||
|
for (int i = 0; i < bytesToRead; i++) {
|
||||||
|
int index = littleEndian ? (offset + i) : (offset + size - 1 - i);
|
||||||
|
result |= ((long) input.luaByte(index)) << (8 * i);
|
||||||
|
}
|
||||||
|
int signIndex = littleEndian ? (offset + size - 1) : offset;
|
||||||
|
boolean negative = (input.luaByte(signIndex) & 0x80) != 0;
|
||||||
|
if (size < 8 && negative) {
|
||||||
|
result |= (-1L) << (size * 8);
|
||||||
|
}
|
||||||
|
if (size > 8) {
|
||||||
|
for (int i = 8; i < size; i++) {
|
||||||
|
int index = littleEndian ? (offset + i) : (offset + size - 1 - i);
|
||||||
|
int b = input.luaByte(index);
|
||||||
|
if (b != (negative ? 0xFF : 0x00)) {
|
||||||
|
throw new LuaError("integer overflow");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long readUnsignedInteger(LuaString input, int offset, int size, boolean littleEndian) {
|
||||||
|
if (size <= 0 || size > 16) {
|
||||||
|
throw new LuaError("integral size out of limits");
|
||||||
|
}
|
||||||
|
requireBytes(input, offset, size);
|
||||||
|
long result = 0L;
|
||||||
|
int bytesToRead = Math.min(size, 8);
|
||||||
|
for (int i = 0; i < bytesToRead; i++) {
|
||||||
|
int index = littleEndian ? (offset + i) : (offset + size - 1 - i);
|
||||||
|
result |= ((long) input.luaByte(index)) << (8 * i);
|
||||||
|
}
|
||||||
|
for (int i = 8; i < size; i++) {
|
||||||
|
int index = littleEndian ? (offset + i) : (offset + size - 1 - i);
|
||||||
|
if (input.luaByte(index) != 0) {
|
||||||
|
throw new LuaError("unsigned overflow");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result < 0) {
|
||||||
|
throw new LuaError("unsigned overflow");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void writeFloat(ByteArrayOutput out, float value, boolean littleEndian) {
|
||||||
|
writeFixed(out, Float.floatToIntBits(value) & 0xFFFFFFFFL, 4, littleEndian);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float readFloat(LuaString input, int offset, boolean littleEndian) {
|
||||||
|
return Float.intBitsToFloat((int) readFixed(input, offset, 4, littleEndian));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void writeDouble(ByteArrayOutput out, double value, boolean littleEndian) {
|
||||||
|
writeFixed(out, Double.doubleToLongBits(value), 8, littleEndian);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double readDouble(LuaString input, int offset, boolean littleEndian) {
|
||||||
|
return Double.longBitsToDouble(readFixed(input, offset, 8, littleEndian));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void writeFixed(ByteArrayOutput out, long bits, int size, boolean littleEndian) {
|
||||||
|
byte[] bytes = new byte[size];
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
int index = littleEndian ? i : (size - 1 - i);
|
||||||
|
bytes[index] = (byte) ((bits >>> (8 * i)) & 0xFF);
|
||||||
|
}
|
||||||
|
out.write(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long readFixed(LuaString input, int offset, int size, boolean littleEndian) {
|
||||||
|
requireBytes(input, offset, size);
|
||||||
|
long bits = 0L;
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
int index = littleEndian ? (offset + i) : (offset + size - 1 - i);
|
||||||
|
bits |= ((long) input.luaByte(index)) << (8 * i);
|
||||||
|
}
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum OptionKind {
|
||||||
|
PADDING,
|
||||||
|
ALIGN,
|
||||||
|
SIGNED,
|
||||||
|
UNSIGNED,
|
||||||
|
FLOAT,
|
||||||
|
DOUBLE,
|
||||||
|
FIXED_STRING,
|
||||||
|
ZERO_STRING,
|
||||||
|
SIZED_STRING
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class FormatOption {
|
||||||
|
final OptionKind kind;
|
||||||
|
final int size;
|
||||||
|
final int alignment;
|
||||||
|
|
||||||
|
FormatOption(OptionKind kind, int size, int alignment) {
|
||||||
|
this.kind = kind;
|
||||||
|
this.size = size;
|
||||||
|
this.alignment = alignment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class FormatState {
|
||||||
|
private final LuaString format;
|
||||||
|
private int index;
|
||||||
|
boolean littleEndian;
|
||||||
|
private int maxAlign;
|
||||||
|
|
||||||
|
FormatState(LuaString format) {
|
||||||
|
this.format = format;
|
||||||
|
this.littleEndian = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
|
||||||
|
this.maxAlign = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasMore() {
|
||||||
|
skipSpaces();
|
||||||
|
return index < format.rawlen();
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatOption next() {
|
||||||
|
while (index < format.rawlen()) {
|
||||||
|
int c = format.luaByte(index++);
|
||||||
|
switch (c) {
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
case '\n':
|
||||||
|
case '\r':
|
||||||
|
continue;
|
||||||
|
case '<':
|
||||||
|
littleEndian = true;
|
||||||
|
continue;
|
||||||
|
case '>':
|
||||||
|
littleEndian = false;
|
||||||
|
continue;
|
||||||
|
case '=':
|
||||||
|
littleEndian = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
|
||||||
|
continue;
|
||||||
|
case '!':
|
||||||
|
maxAlign = readCount();
|
||||||
|
if (maxAlign <= 0) {
|
||||||
|
throw new LuaError("invalid format option '!'");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case 'x':
|
||||||
|
return new FormatOption(OptionKind.PADDING, 1, 1);
|
||||||
|
case 'X': {
|
||||||
|
FormatOption next = peekNextSizedOption();
|
||||||
|
return new FormatOption(OptionKind.ALIGN, alignmentFor(next.size), 1);
|
||||||
|
}
|
||||||
|
case 'b':
|
||||||
|
return signed(1);
|
||||||
|
case 'B':
|
||||||
|
return unsigned(1);
|
||||||
|
case 'h':
|
||||||
|
return signed(2);
|
||||||
|
case 'H':
|
||||||
|
return unsigned(2);
|
||||||
|
case 'l':
|
||||||
|
return signed(8);
|
||||||
|
case 'L':
|
||||||
|
return unsigned(8);
|
||||||
|
case 'j':
|
||||||
|
return signed(8);
|
||||||
|
case 'J':
|
||||||
|
return unsigned(8);
|
||||||
|
case 'T':
|
||||||
|
return unsigned(8);
|
||||||
|
case 'i':
|
||||||
|
return signed(readOptionalCount(4));
|
||||||
|
case 'I':
|
||||||
|
return unsigned(readOptionalCount(4));
|
||||||
|
case 'f':
|
||||||
|
return new FormatOption(OptionKind.FLOAT, 4, alignmentFor(4));
|
||||||
|
case 'd':
|
||||||
|
case 'n':
|
||||||
|
return new FormatOption(OptionKind.DOUBLE, 8, alignmentFor(8));
|
||||||
|
case 'c': {
|
||||||
|
int size = readCount();
|
||||||
|
if (size < 0) {
|
||||||
|
throw new LuaError("missing size for format option 'c'");
|
||||||
|
}
|
||||||
|
return new FormatOption(OptionKind.FIXED_STRING, size, 1);
|
||||||
|
}
|
||||||
|
case 'z':
|
||||||
|
return new FormatOption(OptionKind.ZERO_STRING, 0, 1);
|
||||||
|
case 's': {
|
||||||
|
int size = readOptionalCount(8);
|
||||||
|
return new FormatOption(OptionKind.SIZED_STRING, size, alignmentFor(size));
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new LuaError("invalid format option '" + (char) c + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new LuaError("unexpected end of format string");
|
||||||
|
}
|
||||||
|
|
||||||
|
int alignmentPadding(int offset, FormatOption option) {
|
||||||
|
int alignment = option.alignment;
|
||||||
|
if (alignment <= 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int mod = offset & (alignment - 1);
|
||||||
|
return mod == 0 ? 0 : (alignment - mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FormatOption signed(int size) {
|
||||||
|
validateIntegralSize(size);
|
||||||
|
return new FormatOption(OptionKind.SIGNED, size, alignmentFor(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
private FormatOption unsigned(int size) {
|
||||||
|
validateIntegralSize(size);
|
||||||
|
return new FormatOption(OptionKind.UNSIGNED, size, alignmentFor(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
private FormatOption peekNextSizedOption() {
|
||||||
|
int savedIndex = index;
|
||||||
|
boolean savedEndian = littleEndian;
|
||||||
|
int savedMaxAlign = maxAlign;
|
||||||
|
FormatOption option = next();
|
||||||
|
index = savedIndex;
|
||||||
|
littleEndian = savedEndian;
|
||||||
|
maxAlign = savedMaxAlign;
|
||||||
|
if (option.kind == OptionKind.ZERO_STRING || option.kind == OptionKind.FIXED_STRING) {
|
||||||
|
throw new LuaError("invalid next option for option 'X'");
|
||||||
|
}
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int readCount() {
|
||||||
|
if (index >= format.rawlen() || !Character.isDigit((char) format.luaByte(index))) {
|
||||||
|
throw new LuaError("missing size for format option");
|
||||||
|
}
|
||||||
|
int value = 0;
|
||||||
|
while (index < format.rawlen() && Character.isDigit((char) format.luaByte(index))) {
|
||||||
|
value = value * 10 + (format.luaByte(index++) - '0');
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int readOptionalCount(int defaultValue) {
|
||||||
|
if (index < format.rawlen() && Character.isDigit((char) format.luaByte(index))) {
|
||||||
|
int value = readCount();
|
||||||
|
validateIntegralSize(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int alignmentFor(int size) {
|
||||||
|
int alignment = Math.min(size, maxAlign);
|
||||||
|
if (alignment <= 1) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((alignment & (alignment - 1)) != 0) {
|
||||||
|
throw new LuaError("format asks for alignment not power of 2");
|
||||||
|
}
|
||||||
|
return alignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateIntegralSize(int size) {
|
||||||
|
if (size < 1 || size > 16) {
|
||||||
|
throw new LuaError("integral size out of limits");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void skipSpaces() {
|
||||||
|
while (index < format.rawlen()) {
|
||||||
|
int c = format.luaByte(index);
|
||||||
|
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
|
||||||
|
index++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class ByteArrayOutput {
|
||||||
|
private final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
void writeByte(int value) {
|
||||||
|
out.write(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(byte[] bytes) {
|
||||||
|
out.write(bytes, 0, bytes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(LuaString s) {
|
||||||
|
byte[] bytes = new byte[s.rawlen()];
|
||||||
|
s.copyInto(0, bytes, 0, bytes.length);
|
||||||
|
write(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pad(int count) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
out.write(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int size() {
|
||||||
|
return out.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] toByteArray() {
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This utility method implements both string.find and string.match.
|
* This utility method implements both string.find and string.match.
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.vm2.libs;
|
package org.luaj.vm2.libs;
|
||||||
|
|
||||||
|
import org.luaj.vm2.LuaError;
|
||||||
import org.luaj.vm2.LuaTable;
|
import org.luaj.vm2.LuaTable;
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
@@ -65,6 +66,7 @@ public class TableLib extends TwoArgFunction {
|
|||||||
LuaTable table = new LuaTable();
|
LuaTable table = new LuaTable();
|
||||||
table.set("concat", new concat());
|
table.set("concat", new concat());
|
||||||
table.set("insert", new insert());
|
table.set("insert", new insert());
|
||||||
|
table.set("move", new move());
|
||||||
table.set("pack", new pack());
|
table.set("pack", new pack());
|
||||||
table.set("remove", new remove());
|
table.set("remove", new remove());
|
||||||
table.set("sort", new sort());
|
table.set("sort", new sort());
|
||||||
@@ -123,6 +125,33 @@ public class TableLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "move" (a1, f, e, t [,a2]) -> a2
|
||||||
|
static class move extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
LuaTable source = args.checktable(1);
|
||||||
|
int from = args.checkint(2);
|
||||||
|
int to = args.checkint(3);
|
||||||
|
int target = args.checkint(4);
|
||||||
|
LuaTable dest = args.opttable(5, source);
|
||||||
|
if (to >= from) {
|
||||||
|
int count = to - from + 1;
|
||||||
|
if (count < 0) {
|
||||||
|
throw new LuaError("too many elements to move");
|
||||||
|
}
|
||||||
|
if (target > from && target <= to && dest == source) {
|
||||||
|
for (int i = count - 1; i >= 0; i--) {
|
||||||
|
dest.set(target + i, source.get(from + i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
dest.set(target + i, source.get(from + i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// "remove" (table [, pos]) -> removed-ele
|
// "remove" (table [, pos]) -> removed-ele
|
||||||
static class remove extends VarArgFunction {
|
static class remove extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
|
|||||||
@@ -353,7 +353,7 @@ void FieldSep():
|
|||||||
void Binop():
|
void Binop():
|
||||||
{}
|
{}
|
||||||
{
|
{
|
||||||
"+" | "-" | "*" | "/" | "//" | "^" | "%" | ".." | "<" | "<=" | ">" | ">=" | "==" | "~=" | <AND> | <OR>
|
"+" | "-" | "*" | "/" | "//" | "&" | "|" | "~" | "<<" | ">>" | "^" | "%" | ".." | "<" | "<=" | ">" | ">=" | "==" | "~=" | <AND> | <OR>
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unop():
|
void Unop():
|
||||||
|
|||||||
@@ -510,6 +510,11 @@ int Binop():
|
|||||||
| "*" { return Lua.OP_MUL; }
|
| "*" { return Lua.OP_MUL; }
|
||||||
| "/" { return Lua.OP_DIV; }
|
| "/" { return Lua.OP_DIV; }
|
||||||
| "//" { return Lua.OP_IDIV; }
|
| "//" { return Lua.OP_IDIV; }
|
||||||
|
| "&" { return Lua.OP_BAND; }
|
||||||
|
| "|" { return Lua.OP_BOR; }
|
||||||
|
| "~" { return Lua.OP_BXOR; }
|
||||||
|
| "<<" { return Lua.OP_SHL; }
|
||||||
|
| ">>" { return Lua.OP_SHR; }
|
||||||
| "^" { return Lua.OP_POW; }
|
| "^" { return Lua.OP_POW; }
|
||||||
| "%" { return Lua.OP_MOD; }
|
| "%" { return Lua.OP_MOD; }
|
||||||
| ".." { return Lua.OP_CONCAT; }
|
| ".." { return Lua.OP_CONCAT; }
|
||||||
@@ -529,4 +534,5 @@ int Unop():
|
|||||||
"-" { return Lua.OP_UNM; }
|
"-" { return Lua.OP_UNM; }
|
||||||
| <NOT> { return Lua.OP_NOT; }
|
| <NOT> { return Lua.OP_NOT; }
|
||||||
| "#" { return Lua.OP_LEN; }
|
| "#" { return Lua.OP_LEN; }
|
||||||
|
| "~" { return Lua.OP_BNOT; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import org.luaj.vm2.Globals;
|
|||||||
import org.luaj.vm2.LoadState;
|
import org.luaj.vm2.LoadState;
|
||||||
import org.luaj.vm2.compiler.LuaC;
|
import org.luaj.vm2.compiler.LuaC;
|
||||||
import org.luaj.vm2.libs.BaseLib;
|
import org.luaj.vm2.libs.BaseLib;
|
||||||
import org.luaj.vm2.libs.Bit32Lib;
|
|
||||||
import org.luaj.vm2.libs.CoroutineLib;
|
import org.luaj.vm2.libs.CoroutineLib;
|
||||||
import org.luaj.vm2.libs.DebugLib;
|
import org.luaj.vm2.libs.DebugLib;
|
||||||
import org.luaj.vm2.libs.MathLib;
|
import org.luaj.vm2.libs.MathLib;
|
||||||
@@ -34,6 +33,7 @@ import org.luaj.vm2.libs.PackageLib;
|
|||||||
import org.luaj.vm2.libs.ResourceFinder;
|
import org.luaj.vm2.libs.ResourceFinder;
|
||||||
import org.luaj.vm2.libs.StringLib;
|
import org.luaj.vm2.libs.StringLib;
|
||||||
import org.luaj.vm2.libs.TableLib;
|
import org.luaj.vm2.libs.TableLib;
|
||||||
|
import org.luaj.vm2.libs.Utf8Lib;
|
||||||
|
|
||||||
/** The {@link JmePlatform} class is a convenience class to standardize
|
/** The {@link JmePlatform} class is a convenience class to standardize
|
||||||
* how globals tables are initialized for the JME platform.
|
* how globals tables are initialized for the JME platform.
|
||||||
@@ -73,7 +73,6 @@ import org.luaj.vm2.libs.TableLib;
|
|||||||
* <li>{@link Globals}</li>
|
* <li>{@link Globals}</li>
|
||||||
* <li>{@link BaseLib}</li>
|
* <li>{@link BaseLib}</li>
|
||||||
* <li>{@link PackageLib}</li>
|
* <li>{@link PackageLib}</li>
|
||||||
* <li>{@link Bit32Lib}</li>
|
|
||||||
* <li>{@link TableLib}</li>
|
* <li>{@link TableLib}</li>
|
||||||
* <li>{@link StringLib}</li>
|
* <li>{@link StringLib}</li>
|
||||||
* <li>{@link CoroutineLib}</li>
|
* <li>{@link CoroutineLib}</li>
|
||||||
@@ -105,11 +104,11 @@ public class JmePlatform {
|
|||||||
Globals globals = new Globals();
|
Globals globals = new Globals();
|
||||||
globals.load(new BaseLib());
|
globals.load(new BaseLib());
|
||||||
globals.load(new PackageLib());
|
globals.load(new PackageLib());
|
||||||
globals.load(new Bit32Lib());
|
|
||||||
globals.load(new OsLib());
|
globals.load(new OsLib());
|
||||||
globals.load(new MathLib());
|
globals.load(new MathLib());
|
||||||
globals.load(new TableLib());
|
globals.load(new TableLib());
|
||||||
globals.load(new StringLib());
|
globals.load(new StringLib());
|
||||||
|
globals.load(new Utf8Lib());
|
||||||
globals.load(new CoroutineLib());
|
globals.load(new CoroutineLib());
|
||||||
globals.load(new JmeIoLib());
|
globals.load(new JmeIoLib());
|
||||||
LoadState.install(globals);
|
LoadState.install(globals);
|
||||||
|
|||||||
@@ -89,11 +89,15 @@ public class Exp extends SyntaxElement {
|
|||||||
case Lua.OP_OR: return 0;
|
case Lua.OP_OR: return 0;
|
||||||
case Lua.OP_AND: return 1;
|
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_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_BOR: return 3;
|
||||||
case Lua.OP_ADD: case Lua.OP_SUB: return 4;
|
case Lua.OP_BXOR: return 4;
|
||||||
case Lua.OP_MUL: case Lua.OP_DIV: case Lua.OP_IDIV: case Lua.OP_MOD: return 5;
|
case Lua.OP_BAND: return 5;
|
||||||
case Lua.OP_NOT: case Lua.OP_UNM: case Lua.OP_LEN: return 6;
|
case Lua.OP_SHL: case Lua.OP_SHR: return 6;
|
||||||
case Lua.OP_POW: return 7;
|
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);
|
default: throw new IllegalStateException("precedence of bad op "+op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ public class CoerceJavaToLua {
|
|||||||
private static final class IntCoercion implements Coercion {
|
private static final class IntCoercion implements Coercion {
|
||||||
public LuaValue coerce( Object javaValue ) {
|
public LuaValue coerce( Object javaValue ) {
|
||||||
Number n = (Number) 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( Character.class, charCoercion );
|
||||||
COERCIONS.put( Short.class, intCoercion );
|
COERCIONS.put( Short.class, intCoercion );
|
||||||
COERCIONS.put( Integer.class, intCoercion );
|
COERCIONS.put( Integer.class, intCoercion );
|
||||||
COERCIONS.put( Long.class, doubleCoercion );
|
COERCIONS.put( Long.class, intCoercion );
|
||||||
COERCIONS.put( Float.class, doubleCoercion );
|
COERCIONS.put( Float.class, doubleCoercion );
|
||||||
COERCIONS.put( Double.class, doubleCoercion );
|
COERCIONS.put( Double.class, doubleCoercion );
|
||||||
COERCIONS.put( String.class, stringCoercion );
|
COERCIONS.put( String.class, stringCoercion );
|
||||||
@@ -160,9 +160,9 @@ public class CoerceJavaToLua {
|
|||||||
/**
|
/**
|
||||||
* Coerse a Java object to a corresponding lua value.
|
* Coerse a Java object to a corresponding lua value.
|
||||||
* <p>
|
* <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};
|
* 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};
|
* {@code String} and {@code byte[]} will become {@link LuaString};
|
||||||
* types inheriting from {@link LuaValue} will be returned without coercion;
|
* types inheriting from {@link LuaValue} will be returned without coercion;
|
||||||
* other types will become {@link LuaUserdata}.
|
* other types will become {@link LuaUserdata}.
|
||||||
|
|||||||
@@ -292,7 +292,10 @@ public class CoerceLuaToJava {
|
|||||||
public int score(LuaValue value) {
|
public int score(LuaValue value) {
|
||||||
switch ( value.type() ) {
|
switch ( value.type() ) {
|
||||||
case LuaValue.TNUMBER:
|
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:
|
case LuaValue.TBOOLEAN:
|
||||||
return inheritanceLevels( targetType, Boolean.class );
|
return inheritanceLevels( targetType, Boolean.class );
|
||||||
case LuaValue.TSTRING:
|
case LuaValue.TSTRING:
|
||||||
@@ -308,7 +311,10 @@ public class CoerceLuaToJava {
|
|||||||
public Object coerce(LuaValue value) {
|
public Object coerce(LuaValue value) {
|
||||||
switch ( value.type() ) {
|
switch ( value.type() ) {
|
||||||
case LuaValue.TNUMBER:
|
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:
|
case LuaValue.TBOOLEAN:
|
||||||
return value.toboolean()? Boolean.TRUE: Boolean.FALSE;
|
return value.toboolean()? Boolean.TRUE: Boolean.FALSE;
|
||||||
case LuaValue.TSTRING:
|
case LuaValue.TSTRING:
|
||||||
@@ -369,4 +375,4 @@ public class CoerceLuaToJava {
|
|||||||
COERCIONS.put( c, co );
|
COERCIONS.put( c, co );
|
||||||
return co;
|
return co;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ import org.luaj.vm2.LoadState;
|
|||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
import org.luaj.vm2.compiler.LuaC;
|
import org.luaj.vm2.compiler.LuaC;
|
||||||
import org.luaj.vm2.libs.Bit32Lib;
|
|
||||||
import org.luaj.vm2.libs.CoroutineLib;
|
import org.luaj.vm2.libs.CoroutineLib;
|
||||||
import org.luaj.vm2.libs.DebugLib;
|
import org.luaj.vm2.libs.DebugLib;
|
||||||
import org.luaj.vm2.libs.PackageLib;
|
import org.luaj.vm2.libs.PackageLib;
|
||||||
import org.luaj.vm2.libs.ResourceFinder;
|
import org.luaj.vm2.libs.ResourceFinder;
|
||||||
import org.luaj.vm2.libs.StringLib;
|
import org.luaj.vm2.libs.StringLib;
|
||||||
import org.luaj.vm2.libs.TableLib;
|
import org.luaj.vm2.libs.TableLib;
|
||||||
|
import org.luaj.vm2.libs.Utf8Lib;
|
||||||
|
|
||||||
/** The {@link JsePlatform} class is a convenience class to standardize
|
/** The {@link JsePlatform} class is a convenience class to standardize
|
||||||
* how globals tables are initialized for the JSE platform.
|
* 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 Globals}</li>
|
||||||
* <li>{@link JseBaseLib}</li>
|
* <li>{@link JseBaseLib}</li>
|
||||||
* <li>{@link PackageLib}</li>
|
* <li>{@link PackageLib}</li>
|
||||||
* <li>{@link Bit32Lib}</li>
|
|
||||||
* <li>{@link TableLib}</li>
|
* <li>{@link TableLib}</li>
|
||||||
* <li>{@link StringLib}</li>
|
* <li>{@link StringLib}</li>
|
||||||
* <li>{@link CoroutineLib}</li>
|
* <li>{@link CoroutineLib}</li>
|
||||||
@@ -95,9 +94,9 @@ public class JsePlatform {
|
|||||||
Globals globals = new Globals();
|
Globals globals = new Globals();
|
||||||
globals.load(new JseBaseLib());
|
globals.load(new JseBaseLib());
|
||||||
globals.load(new PackageLib());
|
globals.load(new PackageLib());
|
||||||
globals.load(new Bit32Lib());
|
|
||||||
globals.load(new TableLib());
|
globals.load(new TableLib());
|
||||||
globals.load(new JseStringLib());
|
globals.load(new JseStringLib());
|
||||||
|
globals.load(new Utf8Lib());
|
||||||
globals.load(new CoroutineLib());
|
globals.load(new CoroutineLib());
|
||||||
globals.load(new JseMathLib());
|
globals.load(new JseMathLib());
|
||||||
globals.load(new JseIoLib());
|
globals.load(new JseIoLib());
|
||||||
|
|||||||
@@ -520,6 +520,7 @@ public class JavaBuilder {
|
|||||||
switch (o) {
|
switch (o) {
|
||||||
default:
|
default:
|
||||||
case Lua.OP_UNM: op = "neg"; break;
|
case Lua.OP_UNM: op = "neg"; break;
|
||||||
|
case Lua.OP_BNOT: op = "bnot"; break;
|
||||||
case Lua.OP_NOT: op = "not"; break;
|
case Lua.OP_NOT: op = "not"; break;
|
||||||
case Lua.OP_LEN: op = "len"; 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_MUL: op = "mul"; break;
|
||||||
case Lua.OP_DIV: op = "div"; break;
|
case Lua.OP_DIV: op = "div"; break;
|
||||||
case Lua.OP_IDIV: op = "idiv"; 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_MOD: op = "mod"; break;
|
||||||
case Lua.OP_POW: op = "pow"; break;
|
case Lua.OP_POW: op = "pow"; break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ public class JavaGen {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Lua.OP_UNM: /* 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_NOT: /* A B R(A):= not R(B) */
|
||||||
case Lua.OP_LEN: /* A B R(A):= length of R(B) */
|
case Lua.OP_LEN: /* A B R(A):= length of R(B) */
|
||||||
builder.loadLocal( pc, 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_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_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_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_MOD: /* A B C R(A):= RK(B) % RK(C) */
|
||||||
case Lua.OP_POW: /* 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 );
|
loadLocalOrConstant( p, builder, pc, b );
|
||||||
|
|||||||
@@ -176,6 +176,7 @@ public class ProtoInfo {
|
|||||||
|
|
||||||
case Lua.OP_MOVE:/* A B R(A) := R(B) */
|
case Lua.OP_MOVE:/* A B R(A) := R(B) */
|
||||||
case Lua.OP_UNM: /* 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_NOT: /* A B R(A) := not R(B) */
|
||||||
case Lua.OP_LEN: /* A B R(A) := length of 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++ */
|
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_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_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_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_MOD: /* A B C R(A) := RK(B) % RK(C) */
|
||||||
case Lua.OP_POW: /* 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 );
|
a = Lua.GETARG_A( ins );
|
||||||
|
|||||||
@@ -980,6 +980,26 @@ public class LuaParser implements LuaParserConstants {
|
|||||||
jj_consume_token(85);
|
jj_consume_token(85);
|
||||||
{if (true) return Lua.OP_DIV;}
|
{if (true) return Lua.OP_DIV;}
|
||||||
break;
|
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:
|
case 86:
|
||||||
jj_consume_token(86);
|
jj_consume_token(86);
|
||||||
{if (true) return Lua.OP_POW;}
|
{if (true) return Lua.OP_POW;}
|
||||||
@@ -1046,6 +1066,10 @@ public class LuaParser implements LuaParserConstants {
|
|||||||
jj_consume_token(69);
|
jj_consume_token(69);
|
||||||
{if (true) return Lua.OP_LEN;}
|
{if (true) return Lua.OP_LEN;}
|
||||||
break;
|
break;
|
||||||
|
case BNOT:
|
||||||
|
jj_consume_token(BNOT);
|
||||||
|
{if (true) return Lua.OP_BNOT;}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
jj_la1[33] = jj_gen;
|
jj_la1[33] = jj_gen;
|
||||||
jj_consume_token(-1);
|
jj_consume_token(-1);
|
||||||
|
|||||||
@@ -114,6 +114,16 @@ public interface LuaParserConstants {
|
|||||||
int CHAR = 67;
|
int CHAR = 67;
|
||||||
/** RegularExpression Id. */
|
/** RegularExpression Id. */
|
||||||
int LF = 68;
|
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. */
|
/** Lexical state. */
|
||||||
int DEFAULT = 0;
|
int DEFAULT = 0;
|
||||||
@@ -237,6 +247,11 @@ public interface LuaParserConstants {
|
|||||||
"\">=\"",
|
"\">=\"",
|
||||||
"\"==\"",
|
"\"==\"",
|
||||||
"\"~=\"",
|
"\"~=\"",
|
||||||
|
"\"~\"",
|
||||||
|
"\"&\"",
|
||||||
|
"\"|\"",
|
||||||
|
"\"<<\"",
|
||||||
|
"\">>\"",
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -450,6 +450,8 @@ private int jjMoveStringLiteralDfa0_0()
|
|||||||
{
|
{
|
||||||
case 35:
|
case 35:
|
||||||
return jjStopAtPos(0, 69);
|
return jjStopAtPos(0, 69);
|
||||||
|
case 38:
|
||||||
|
return jjStopAtPos(0, 96);
|
||||||
case 37:
|
case 37:
|
||||||
return jjStopAtPos(0, 87);
|
return jjStopAtPos(0, 87);
|
||||||
case 40:
|
case 40:
|
||||||
@@ -478,13 +480,13 @@ private int jjMoveStringLiteralDfa0_0()
|
|||||||
return jjStopAtPos(0, 70);
|
return jjStopAtPos(0, 70);
|
||||||
case 60:
|
case 60:
|
||||||
jjmatchedKind = 89;
|
jjmatchedKind = 89;
|
||||||
return jjMoveStringLiteralDfa1_0(0x0L, 0x4000000L);
|
return jjMoveStringLiteralDfa1_0(0x0L, 0x84000000L);
|
||||||
case 61:
|
case 61:
|
||||||
jjmatchedKind = 71;
|
jjmatchedKind = 71;
|
||||||
return jjMoveStringLiteralDfa1_0(0x0L, 0x20000000L);
|
return jjMoveStringLiteralDfa1_0(0x0L, 0x20000000L);
|
||||||
case 62:
|
case 62:
|
||||||
jjmatchedKind = 91;
|
jjmatchedKind = 91;
|
||||||
return jjMoveStringLiteralDfa1_0(0x0L, 0x10000000L);
|
return jjMoveStringLiteralDfa1_0(0x0L, 0x110000000L);
|
||||||
case 91:
|
case 91:
|
||||||
jjmatchedKind = 77;
|
jjmatchedKind = 77;
|
||||||
return jjMoveStringLiteralDfa1_0(0x7800L, 0x0L);
|
return jjMoveStringLiteralDfa1_0(0x7800L, 0x0L);
|
||||||
@@ -525,6 +527,7 @@ private int jjMoveStringLiteralDfa0_0()
|
|||||||
case 125:
|
case 125:
|
||||||
return jjStopAtPos(0, 81);
|
return jjStopAtPos(0, 81);
|
||||||
case 126:
|
case 126:
|
||||||
|
jjmatchedKind = 95;
|
||||||
return jjMoveStringLiteralDfa1_0(0x0L, 0x40000000L);
|
return jjMoveStringLiteralDfa1_0(0x0L, 0x40000000L);
|
||||||
default :
|
default :
|
||||||
return jjMoveNfa_0(8, 0);
|
return jjMoveNfa_0(8, 0);
|
||||||
@@ -557,10 +560,18 @@ private int jjMoveStringLiteralDfa1_0(long active0, long active1)
|
|||||||
if ((active1 & 0x1L) != 0L)
|
if ((active1 & 0x1L) != 0L)
|
||||||
return jjStopAtPos(1, 28);
|
return jjStopAtPos(1, 28);
|
||||||
break;
|
break;
|
||||||
|
case 60:
|
||||||
|
if ((active1 & 0x80000000L) != 0L)
|
||||||
|
return jjStopAtPos(1, 98);
|
||||||
|
break;
|
||||||
case 58:
|
case 58:
|
||||||
if ((active1 & 0x2L) != 0L)
|
if ((active1 & 0x2L) != 0L)
|
||||||
return jjStopAtPos(1, 65);
|
return jjStopAtPos(1, 65);
|
||||||
break;
|
break;
|
||||||
|
case 62:
|
||||||
|
if ((active1 & 0x100000000L) != 0L)
|
||||||
|
return jjStopAtPos(1, 99);
|
||||||
|
break;
|
||||||
case 61:
|
case 61:
|
||||||
if ((active1 & 0x4000000L) != 0L)
|
if ((active1 & 0x4000000L) != 0L)
|
||||||
return jjStopAtPos(1, 90);
|
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,
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
};
|
};
|
||||||
static final long[] jjtoToken = {
|
static final long[] jjtoToken = {
|
||||||
0x601fffffef800001L, 0x7fffffe2L,
|
0x601fffffef800001L, 0xfffffffe2L,
|
||||||
};
|
};
|
||||||
static final long[] jjtoSkip = {
|
static final long[] jjtoSkip = {
|
||||||
0x7e003eL, 0x0L,
|
0x7e003eL, 0x0L,
|
||||||
@@ -2105,3 +2116,5 @@ private void jjCheckNAddStates(int start, int end)
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
case 124:
|
||||||
|
return jjStopAtPos(0, 97);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin
|
|||||||
private static final String __NAME__ = "Luaj";
|
private static final String __NAME__ = "Luaj";
|
||||||
private static final String __SHORT_NAME__ = "Luaj";
|
private static final String __SHORT_NAME__ = "Luaj";
|
||||||
private static final String __LANGUAGE__ = "lua";
|
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 __ARGV__ = "arg";
|
||||||
private static final String __FILENAME__ = "?";
|
private static final String __FILENAME__ = "?";
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin
|
|||||||
case LuaValue.TSTRING: return luajValue.tojstring();
|
case LuaValue.TSTRING: return luajValue.tojstring();
|
||||||
case LuaValue.TUSERDATA: return luajValue.checkuserdata(Object.class);
|
case LuaValue.TUSERDATA: return luajValue.checkuserdata(Object.class);
|
||||||
case LuaValue.TNUMBER: return luajValue.isinttype()?
|
case LuaValue.TNUMBER: return luajValue.isinttype()?
|
||||||
(Object) Integer.valueOf(luajValue.toint()):
|
(Object) Long.valueOf(luajValue.tolong()):
|
||||||
(Object) Double.valueOf(luajValue.todouble());
|
(Object) Double.valueOf(luajValue.todouble());
|
||||||
default: return luajValue;
|
default: return luajValue;
|
||||||
}
|
}
|
||||||
@@ -263,4 +263,4 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,6 +116,127 @@ public class FragmentsTest extends TestSuite {
|
|||||||
public void testFloorDivisionInExpression() {
|
public void testFloorDivisionInExpression() {
|
||||||
runFragment(LuaValue.TRUE, "local x=5 local width=10 return x==width//2\n");
|
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() {
|
public void testForloopParamUpvalues() {
|
||||||
runFragment( LuaValue.varargsOf(new LuaValue[] {
|
runFragment( LuaValue.varargsOf(new LuaValue[] {
|
||||||
|
|||||||
@@ -40,6 +40,20 @@ public class LuaJavaCoercionTest extends TestCase {
|
|||||||
assertEquals( Integer.class, o.getClass() );
|
assertEquals( Integer.class, o.getClass() );
|
||||||
assertEquals( new Integer(777), o );
|
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() {
|
public void testJavaStringToLuaString() {
|
||||||
String s = new String("777");
|
String s = new String("777");
|
||||||
|
|||||||
Reference in New Issue
Block a user