Fixed issue: #108

This commit is contained in:
UnlegitDqrk
2026-03-01 19:57:26 +01:00
parent 4c2add3832
commit 01a8bd944e
20 changed files with 120 additions and 40 deletions

View File

@@ -200,39 +200,40 @@ public class Lua {
public static final int OP_SUB = 14; /* A B C R(A) := RK(B) - RK(C) */ public static final int OP_SUB = 14; /* 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_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_MOD = 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_POW = 18; /* 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_UNM = 19; /* A B R(A) := -R(B) */ public static final int OP_POW = 19; /* A B C R(A) := RK(B) ^ RK(C) */
public static final int OP_NOT = 20; /* A B R(A) := not R(B) */ public static final int OP_UNM = 20; /* A B R(A) := -R(B) */
public static final int OP_LEN = 21; /* A B R(A) := length of R(B) */ public static final int OP_NOT = 21; /* A B R(A) := not R(B) */
public static final int OP_LEN = 22; /* A B R(A) := length of R(B) */
public static final int OP_CONCAT = 22; /* A B C R(A) := R(B).. ... ..R(C) */ public static final int OP_CONCAT = 23; /* A B C R(A) := R(B).. ... ..R(C) */
public static final int OP_JMP = 23; /* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */ public static final int OP_JMP = 24; /* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
public static final int OP_EQ = 24; /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ public static final int OP_EQ = 25; /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
public static final int OP_LT = 25; /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ public static final int OP_LT = 26; /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
public static final int OP_LE = 26; /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ public static final int OP_LE = 27; /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
public static final int OP_TEST = 27; /* A C if not (R(A) <=> C) then pc++ */ public static final int OP_TEST = 28; /* A C if not (R(A) <=> C) then pc++ */
public static final int OP_TESTSET = 28; /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ public static final int OP_TESTSET = 29; /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
public static final int OP_CALL = 29; /* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ public static final int OP_CALL = 30; /* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
public static final int OP_TAILCALL = 30; /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ public static final int OP_TAILCALL = 31; /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
public static final int OP_RETURN = 31; /* A B return R(A), ... ,R(A+B-2) (see note) */ public static final int OP_RETURN = 32; /* A B return R(A), ... ,R(A+B-2) (see note) */
public static final int OP_FORLOOP = 32; /* A sBx R(A)+=R(A+2); public static final int OP_FORLOOP = 33; /* 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 = 33; /* A sBx R(A)-=R(A+2); pc+=sBx */ public static final int OP_FORPREP = 34; /* A sBx R(A)-=R(A+2); pc+=sBx */
public static final int OP_TFORCALL = 34; /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */ public static final int OP_TFORCALL = 35; /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
public static final int OP_TFORLOOP = 35; /* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx } */ public static final int OP_TFORLOOP = 36; /* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx } */
public static final int OP_SETLIST = 36; /* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ public static final int OP_SETLIST = 37; /* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
public static final int OP_CLOSURE = 37; /* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ public static final int OP_CLOSURE = 38; /* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
public static final int OP_VARARG = 38; /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ public static final int OP_VARARG = 39; /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
public static final int OP_EXTRAARG = 39; /* Ax extra (larger) argument for previous opcode */ public static final int OP_EXTRAARG = 40; /* 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;
@@ -297,6 +298,7 @@ public class Lua {
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SUB */ (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SUB */
(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_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 */

View File

@@ -348,6 +348,10 @@ public class LuaClosure extends LuaFunction {
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).div((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).div((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue; continue;
case Lua.OP_IDIV: /* A B C R(A):= RK(B) // RK(C) */
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).idiv((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;

View File

@@ -139,9 +139,13 @@ public class LuaDouble extends LuaNumber {
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 ) { return rhs.divInto(v); }
public LuaValue idiv( LuaValue rhs ) { return rhs.idivInto(v); }
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( int rhs ) { return LuaDouble.didiv(v,rhs); }
public LuaValue idivInto( double lhs ) { return LuaDouble.didiv(lhs,v); }
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); }
@@ -159,6 +163,10 @@ public class LuaDouble extends LuaNumber {
return rhs!=0? valueOf( lhs / rhs ): lhs>0? POSINF: lhs==0? NAN: NEGINF; return rhs!=0? valueOf( lhs / rhs ): lhs>0? POSINF: lhs==0? NAN: NEGINF;
} }
public static LuaValue didiv(double lhs, double rhs) {
return valueOf(Math.floor(ddiv_d(lhs, rhs)));
}
/** Divide two double numbers according to lua math, and return a double result. /** Divide two double numbers according to lua math, and return a double result.
* @param lhs Left-hand-side of the division. * @param lhs Left-hand-side of the division.
* @param rhs Right-hand-side of the division. * @param rhs Right-hand-side of the division.

View File

@@ -163,9 +163,13 @@ public class LuaInteger extends LuaNumber {
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 ) { return rhs.divInto(v); }
public LuaValue idiv( LuaValue rhs ) { return rhs.idivInto(v); }
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( int rhs ) { return LuaDouble.didiv(v,rhs); }
public LuaValue idivInto( double lhs ) { return LuaDouble.didiv(lhs,v); }
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); }

View File

@@ -280,9 +280,13 @@ public class LuaString extends LuaValue {
public LuaValue powWith( double lhs ) { return MathLib.dpow(lhs, checkarith()); } public LuaValue powWith( double lhs ) { return MathLib.dpow(lhs, checkarith()); }
public LuaValue powWith( int lhs ) { return MathLib.dpow(lhs, checkarith()); } public LuaValue powWith( int lhs ) { return MathLib.dpow(lhs, checkarith()); }
public LuaValue div( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(DIV,rhs): rhs.divInto(d); } public LuaValue div( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(DIV,rhs): rhs.divInto(d); }
public LuaValue idiv( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(IDIV,rhs): rhs.idivInto(d); }
public LuaValue div( double rhs ) { return LuaDouble.ddiv(checkarith(),rhs); } public LuaValue div( double rhs ) { return LuaDouble.ddiv(checkarith(),rhs); }
public LuaValue div( int rhs ) { return LuaDouble.ddiv(checkarith(),rhs); } public LuaValue div( int rhs ) { return LuaDouble.ddiv(checkarith(),rhs); }
public LuaValue divInto( double lhs ) { return LuaDouble.ddiv(lhs, checkarith()); } public LuaValue divInto( double lhs ) { return LuaDouble.ddiv(lhs, checkarith()); }
public LuaValue idiv( double 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 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); }

View File

@@ -213,6 +213,9 @@ public class LuaValue extends Varargs {
/** LuaString constant with value "__div" for use as metatag */ /** LuaString constant with value "__div" for use as metatag */
public static final LuaString DIV = valueOf("__div"); public static final LuaString DIV = valueOf("__div");
/** LuaString constant with value "__idiv" for use as metatag */
public static final LuaString IDIV = valueOf("__idiv");
/** 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");
@@ -2399,6 +2402,8 @@ 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); }
/** 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
* <p> * <p>
@@ -2414,6 +2419,8 @@ 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"); }
/** 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
* <p> * <p>
@@ -2429,6 +2436,8 @@ 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"); }
/** Reverse-divide: Perform numeric divide operation into another value /** Reverse-divide: Perform numeric divide operation into another value
* with metatag processing * with metatag processing
* <p> * <p>
@@ -2444,6 +2453,8 @@ 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); }
/** Modulo: Perform numeric modulo operation with another value /** Modulo: Perform numeric modulo operation with another value
* of unknown type, * of unknown type,
* including metatag processing. * including metatag processing.

View File

@@ -276,6 +276,7 @@ public class Print extends Lua {
case OP_SUB: case OP_SUB:
case OP_MUL: case OP_MUL:
case OP_DIV: case OP_DIV:
case OP_IDIV:
case OP_POW: case OP_POW:
case OP_EQ: case OP_EQ:
case OP_LT: case OP_LT:

View File

@@ -870,7 +870,7 @@ public class FuncState extends Constants {
LuaValue v1, v2, r; LuaValue v1, v2, r;
if (!e1.isnumeral() || !e2.isnumeral()) if (!e1.isnumeral() || !e2.isnumeral())
return false; return false;
if ((op == OP_DIV || op == OP_MOD) && e2.u.nval().eq_b(LuaValue.ZERO)) if ((op == OP_DIV || op == OP_IDIV || op == OP_MOD) && e2.u.nval().eq_b(LuaValue.ZERO))
return false; /* do not attempt to divide by 0 */ return false; /* do not attempt to divide by 0 */
v1 = e1.u.nval(); v1 = e1.u.nval();
v2 = e2.u.nval(); v2 = e2.u.nval();
@@ -887,6 +887,9 @@ public class FuncState extends Constants {
case OP_DIV: case OP_DIV:
r = v1.div(v2); r = v1.div(v2);
break; break;
case OP_IDIV:
r = v1.idiv(v2);
break;
case OP_MOD: case OP_MOD:
r = v1.mod(v2); r = v1.mod(v2);
break; break;
@@ -991,6 +994,7 @@ public class FuncState extends Constants {
case LexState.OPR_SUB: case LexState.OPR_SUB:
case LexState.OPR_MUL: case LexState.OPR_MUL:
case LexState.OPR_DIV: case LexState.OPR_DIV:
case LexState.OPR_IDIV:
case LexState.OPR_MOD: case LexState.OPR_MOD:
case LexState.OPR_POW: { case LexState.OPR_POW: {
if (!v.isnumeral()) if (!v.isnumeral())
@@ -1050,6 +1054,9 @@ public class FuncState extends Constants {
case LexState.OPR_DIV: case LexState.OPR_DIV:
this.codearith(OP_DIV, e1, e2, line); this.codearith(OP_DIV, e1, e2, line);
break; break;
case LexState.OPR_IDIV:
this.codearith(OP_IDIV, 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;

View File

@@ -85,12 +85,12 @@ public class LexState extends Constants {
** grep "ORDER OPR" if you change these enums ** grep "ORDER OPR" if you change these enums
*/ */
static final int static final int
OPR_ADD=0, OPR_SUB=1, OPR_MUL=2, OPR_DIV=3, OPR_MOD=4, OPR_POW=5, OPR_ADD=0, OPR_SUB=1, OPR_MUL=2, OPR_DIV=3, OPR_IDIV=4, OPR_MOD=5, OPR_POW=6,
OPR_CONCAT=6, OPR_CONCAT=7,
OPR_NE=7, OPR_EQ=8, OPR_NE=8, OPR_EQ=9,
OPR_LT=9, OPR_LE=10, OPR_GT=11, OPR_GE=12, OPR_LT=10, OPR_LE=11, OPR_GT=12, OPR_GE=13,
OPR_AND=13, OPR_OR=14, OPR_AND=14, OPR_OR=15,
OPR_NOBINOPR=15; OPR_NOBINOPR=16;
static final int static final int
OPR_MINUS=0, OPR_NOT=1, OPR_LEN=2, OPR_NOUNOPR=3; OPR_MINUS=0, OPR_NOT=1, OPR_LEN=2, OPR_NOUNOPR=3;
@@ -149,7 +149,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 +160,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_EQ=281, TK_GE=282, TK_LE=283, TK_NE=284, TK_CONCAT=279, TK_DOTS=280, TK_IDIV=281, TK_EQ=282, TK_GE=283, TK_LE=284, TK_NE=285,
TK_DBCOLON=285, TK_EOS=286, TK_NUMBER=287, TK_NAME=288, TK_STRING=289; TK_DBCOLON=286, TK_EOS=287, TK_NUMBER=288, TK_NAME=289, TK_STRING=290;
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;
@@ -674,6 +674,15 @@ public class LexState extends Constants {
return TK_DBCOLON; return TK_DBCOLON;
} }
} }
case '/': {
nextChar();
if (current != '/')
return '/';
else {
nextChar();
return TK_IDIV;
}
}
case '"': case '"':
case '\'': { case '\'': {
read_string(current, seminfo); read_string(current, seminfo);
@@ -1517,6 +1526,8 @@ public class LexState extends Constants {
return OPR_MUL; return OPR_MUL;
case '/': case '/':
return OPR_DIV; return OPR_DIV;
case TK_IDIV:
return OPR_IDIV;
case '%': case '%':
return OPR_MOD; return OPR_MOD;
case '^': case '^':
@@ -1556,7 +1567,7 @@ 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(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, 9), new Priority(5, 4), /* power and concat (right associative) */ new Priority(10, 9), new Priority(5, 4), /* power and concat (right associative) */
new Priority(3, 3), new Priority(3, 3), /* equality and inequality */ new Priority(3, 3), new Priority(3, 3), /* equality and inequality */
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(3, 3), new Priority(3, 3), /* order */

View File

@@ -816,6 +816,7 @@ public class DebugLib extends TwoArgFunction {
case Lua.OP_SUB: tm = LuaValue.SUB; break; case Lua.OP_SUB: tm = LuaValue.SUB; break;
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_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;

View File

@@ -353,7 +353,7 @@ void FieldSep():
void Binop(): void Binop():
{} {}
{ {
"+" | "-" | "*" | "/" | "^" | "%" | ".." | "<" | "<=" | ">" | ">=" | "==" | "~=" | <AND> | <OR> "+" | "-" | "*" | "/" | "//" | "^" | "%" | ".." | "<" | "<=" | ">" | ">=" | "==" | "~=" | <AND> | <OR>
} }
void Unop(): void Unop():

View File

@@ -509,6 +509,7 @@ int Binop():
| "-" { return Lua.OP_SUB; } | "-" { return Lua.OP_SUB; }
| "*" { return Lua.OP_MUL; } | "*" { return Lua.OP_MUL; }
| "/" { return Lua.OP_DIV; } | "/" { return Lua.OP_DIV; }
| "//" { return Lua.OP_IDIV; }
| "^" { return Lua.OP_POW; } | "^" { return Lua.OP_POW; }
| "%" { return Lua.OP_MOD; } | "%" { return Lua.OP_MOD; }
| ".." { return Lua.OP_CONCAT; } | ".." { return Lua.OP_CONCAT; }

View File

@@ -91,7 +91,7 @@ public class Exp extends SyntaxElement {
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_CONCAT: return 3;
case Lua.OP_ADD: case Lua.OP_SUB: return 4; case Lua.OP_ADD: case Lua.OP_SUB: return 4;
case Lua.OP_MUL: case Lua.OP_DIV: case Lua.OP_MOD: return 5; case Lua.OP_MUL: case Lua.OP_DIV: case Lua.OP_IDIV: case Lua.OP_MOD: return 5;
case Lua.OP_NOT: case Lua.OP_UNM: case Lua.OP_LEN: return 6; case Lua.OP_NOT: case Lua.OP_UNM: case Lua.OP_LEN: return 6;
case Lua.OP_POW: return 7; case Lua.OP_POW: return 7;
default: throw new IllegalStateException("precedence of bad op "+op); default: throw new IllegalStateException("precedence of bad op "+op);

View File

@@ -534,6 +534,7 @@ public class JavaBuilder {
case Lua.OP_SUB: op = "sub"; break; case Lua.OP_SUB: op = "sub"; break;
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_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;
} }

View File

@@ -165,6 +165,7 @@ public class JavaGen {
case Lua.OP_SUB: /* A B C R(A):= RK(B) - RK(C) */ case Lua.OP_SUB: /* 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_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_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 );

View File

@@ -189,6 +189,7 @@ public class ProtoInfo {
case Lua.OP_SUB: /* A B C R(A) := RK(B) - RK(C) */ case Lua.OP_SUB: /* 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_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_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 );

View File

@@ -960,6 +960,10 @@ public class LuaParser implements LuaParserConstants {
final public int Binop() throws ParseException { final public int Binop() throws ParseException {
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case IDIV:
jj_consume_token(IDIV);
{if (true) return Lua.OP_IDIV;}
break;
case 82: case 82:
jj_consume_token(82); jj_consume_token(82);
{if (true) return Lua.OP_ADD;} {if (true) return Lua.OP_ADD;}

View File

@@ -33,6 +33,8 @@ public interface LuaParserConstants {
/** RegularExpression Id. */ /** RegularExpression Id. */
int LONGSTRINGN = 27; int LONGSTRINGN = 27;
/** RegularExpression Id. */ /** RegularExpression Id. */
int IDIV = 28;
/** RegularExpression Id. */
int AND = 29; int AND = 29;
/** RegularExpression Id. */ /** RegularExpression Id. */
int BREAK = 30; int BREAK = 30;
@@ -168,7 +170,7 @@ public interface LuaParserConstants {
"\"]==]\"", "\"]==]\"",
"\"]===]\"", "\"]===]\"",
"<LONGSTRINGN>", "<LONGSTRINGN>",
"<token of kind 28>", "\"//\"",
"\"and\"", "\"and\"",
"\"break\"", "\"break\"",
"\"do\"", "\"do\"",

View File

@@ -469,7 +469,8 @@ private int jjMoveStringLiteralDfa0_0()
jjmatchedKind = 73; jjmatchedKind = 73;
return jjMoveStringLiteralDfa1_0(0x0L, 0x1008000L); return jjMoveStringLiteralDfa1_0(0x0L, 0x1008000L);
case 47: case 47:
return jjStopAtPos(0, 85); jjmatchedKind = 85;
return jjMoveStringLiteralDfa1_0(0x0L, 0x1L);
case 58: case 58:
jjmatchedKind = 74; jjmatchedKind = 74;
return jjMoveStringLiteralDfa1_0(0x0L, 0x2L); return jjMoveStringLiteralDfa1_0(0x0L, 0x2L);
@@ -552,6 +553,10 @@ private int jjMoveStringLiteralDfa1_0(long active0, long active1)
jjmatchedPos = 1; jjmatchedPos = 1;
} }
return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x8000L); return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x8000L);
case 47:
if ((active1 & 0x1L) != 0L)
return jjStopAtPos(1, 28);
break;
case 58: case 58:
if ((active1 & 0x2L) != 0L) if ((active1 & 0x2L) != 0L)
return jjStopAtPos(1, 65); return jjStopAtPos(1, 65);

View File

@@ -105,6 +105,18 @@ public class FragmentsTest extends TestSuite {
} }
public void testFloorDivision() {
runFragment(LuaValue.valueOf(2), "return 5//2\n");
}
public void testFloorDivisionNegativeRoundsDown() {
runFragment(LuaValue.valueOf(-3), "return 5//-2\n");
}
public void testFloorDivisionInExpression() {
runFragment(LuaValue.TRUE, "local x=5 local width=10 return x==width//2\n");
}
public void testForloopParamUpvalues() { public void testForloopParamUpvalues() {
runFragment( LuaValue.varargsOf(new LuaValue[] { runFragment( LuaValue.varargsOf(new LuaValue[] {
LuaValue.valueOf(77), LuaValue.valueOf(77),