Fix compiler varargs support, add tests for varargs compatibility.
This commit is contained in:
@@ -209,7 +209,7 @@ public class DumpState {
|
|||||||
dumpInt(f.lastlinedefined);
|
dumpInt(f.lastlinedefined);
|
||||||
dumpChar(f.nups);
|
dumpChar(f.nups);
|
||||||
dumpChar(f.numparams);
|
dumpChar(f.numparams);
|
||||||
dumpChar(f.is_vararg? 1: 0);
|
dumpChar(f.is_vararg);
|
||||||
dumpChar(f.maxstacksize);
|
dumpChar(f.maxstacksize);
|
||||||
dumpCode(f);
|
dumpCode(f);
|
||||||
dumpConstants(f);
|
dumpConstants(f);
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ public class FuncState extends LuaC {
|
|||||||
short nactvar; /* number of active local variables */
|
short nactvar; /* number of active local variables */
|
||||||
upvaldesc upvalues[] = new upvaldesc[LUAI_MAXUPVALUES]; /* upvalues */
|
upvaldesc upvalues[] = new upvaldesc[LUAI_MAXUPVALUES]; /* upvalues */
|
||||||
short actvar[] = new short[LUAI_MAXVARS]; /* declared-variable stack */
|
short actvar[] = new short[LUAI_MAXVARS]; /* declared-variable stack */
|
||||||
int varargflags; /* whether varargs are needed */
|
|
||||||
|
|
||||||
FuncState() {
|
FuncState() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ public class LexState {
|
|||||||
private static final String LUA_QS(String s) { return "'"+s+"'"; }
|
private static final String LUA_QS(String s) { return "'"+s+"'"; }
|
||||||
private static final String LUA_QL(Object o) { return LUA_QS(String.valueOf(o)); }
|
private static final String LUA_QL(Object o) { return LUA_QS(String.valueOf(o)); }
|
||||||
|
|
||||||
|
|
||||||
private static final int LUA_COMPAT_LSTR = 1; // 1 for compatibility, 2 for old behavior
|
private static final int LUA_COMPAT_LSTR = 1; // 1 for compatibility, 2 for old behavior
|
||||||
private static final boolean LUA_COMPAT_VARARG = true;
|
private static final boolean LUA_COMPAT_VARARG = true;
|
||||||
|
|
||||||
@@ -917,7 +916,6 @@ public class LexState {
|
|||||||
f.maxstacksize = 2; /* registers 0/1 are always valid */
|
f.maxstacksize = 2; /* registers 0/1 are always valid */
|
||||||
//fs.h = new LTable();
|
//fs.h = new LTable();
|
||||||
fs.htable = new Hashtable();
|
fs.htable = new Hashtable();
|
||||||
fs.varargflags = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_func() {
|
void close_func() {
|
||||||
@@ -1076,7 +1074,7 @@ public class LexState {
|
|||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
LPrototype f = fs.f;
|
LPrototype f = fs.f;
|
||||||
int nparams = 0;
|
int nparams = 0;
|
||||||
f.is_vararg = false;
|
f.is_vararg = 0;
|
||||||
if (this.t.token != ')') { /* is `parlist' not empty? */
|
if (this.t.token != ')') { /* is `parlist' not empty? */
|
||||||
do {
|
do {
|
||||||
switch (this.t.token) {
|
switch (this.t.token) {
|
||||||
@@ -1089,20 +1087,17 @@ public class LexState {
|
|||||||
if (LUA_COMPAT_VARARG) {
|
if (LUA_COMPAT_VARARG) {
|
||||||
/* use `arg' as default name */
|
/* use `arg' as default name */
|
||||||
this.new_localvarliteral("arg", nparams++);
|
this.new_localvarliteral("arg", nparams++);
|
||||||
// f.is_vararg = VARARG_HASARG | VARARG_NEEDSARG;
|
f.is_vararg = LuaC.VARARG_HASARG | LuaC.VARARG_NEEDSARG;
|
||||||
fs.varargflags = LuaC.VARARG_HASARG | LuaC.VARARG_NEEDSARG;
|
|
||||||
}
|
}
|
||||||
// f.is_vararg |= VARARG_ISVARARG;
|
f.is_vararg |= LuaC.VARARG_ISVARARG;
|
||||||
fs.varargflags |= LuaC.VARARG_ISVARARG;
|
|
||||||
f.is_vararg = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: this.syntaxerror("<name> or " + LUA_QL("...") + " expected");
|
default: this.syntaxerror("<name> or " + LUA_QL("...") + " expected");
|
||||||
}
|
}
|
||||||
} while (!f.is_vararg && this.testnext(','));
|
} while ((f.is_vararg==0) && this.testnext(','));
|
||||||
}
|
}
|
||||||
this.adjustlocalvars(nparams);
|
this.adjustlocalvars(nparams);
|
||||||
f.numparams = (fs.nactvar - (fs.varargflags & LuaC.VARARG_HASARG));
|
f.numparams = (fs.nactvar - (f.is_vararg & LuaC.VARARG_HASARG));
|
||||||
fs.reserveregs(fs.nactvar); /* reserve register for parameters */
|
fs.reserveregs(fs.nactvar); /* reserve register for parameters */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1288,11 +1283,9 @@ public class LexState {
|
|||||||
}
|
}
|
||||||
case TK_DOTS: { /* vararg */
|
case TK_DOTS: { /* vararg */
|
||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
this.check_condition(fs.f.is_vararg, "cannot use " + LUA_QL("...")
|
this.check_condition(fs.f.is_vararg!=0, "cannot use " + LUA_QL("...")
|
||||||
+ " outside a vararg function");
|
+ " outside a vararg function");
|
||||||
// fs.f.is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */
|
fs.f.is_vararg &= ~LuaC.VARARG_NEEDSARG; /* don't need 'arg' */
|
||||||
fs.varargflags &= ~LuaC.VARARG_NEEDSARG; /* don't need 'arg' */
|
|
||||||
fs.f.is_vararg = (fs.varargflags != 0);
|
|
||||||
v.init(VVARARG, fs.codeABC(Lua.OP_VARARG, 0, 1, 0));
|
v.init(VVARARG, fs.codeABC(Lua.OP_VARARG, 0, 1, 0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,8 +196,7 @@ public class LuaC extends Lua implements LuaCompiler {
|
|||||||
lexstate.setinput( this, firstByte, z, new LString(name) );
|
lexstate.setinput( this, firstByte, z, new LString(name) );
|
||||||
lexstate.open_func(funcstate);
|
lexstate.open_func(funcstate);
|
||||||
/* main func. is always vararg */
|
/* main func. is always vararg */
|
||||||
funcstate.varargflags = LuaC.VARARG_ISVARARG;
|
funcstate.f.is_vararg = LuaC.VARARG_ISVARARG;
|
||||||
funcstate.f.is_vararg = true;
|
|
||||||
funcstate.f.source = new LString("@"+name);
|
funcstate.f.source = new LString("@"+name);
|
||||||
lexstate.next(); /* read first token */
|
lexstate.next(); /* read first token */
|
||||||
lexstate.chunk();
|
lexstate.chunk();
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class LPrototype {
|
|||||||
public int linedefined;
|
public int linedefined;
|
||||||
public int lastlinedefined;
|
public int lastlinedefined;
|
||||||
public int numparams;
|
public int numparams;
|
||||||
public boolean is_vararg;
|
public int is_vararg;
|
||||||
public int maxstacksize;
|
public int maxstacksize;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ public class LoadState {
|
|||||||
f.lastlinedefined = loadInt();
|
f.lastlinedefined = loadInt();
|
||||||
f.nups = is.readUnsignedByte();
|
f.nups = is.readUnsignedByte();
|
||||||
f.numparams = is.readUnsignedByte();
|
f.numparams = is.readUnsignedByte();
|
||||||
f.is_vararg = (0 != is.readUnsignedByte());
|
f.is_vararg = is.readUnsignedByte();
|
||||||
f.maxstacksize = is.readUnsignedByte();
|
f.maxstacksize = is.readUnsignedByte();
|
||||||
f.code = loadIntArray();
|
f.code = loadIntArray();
|
||||||
loadConstants(f);
|
loadConstants(f);
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ public class LuaState extends Lua {
|
|||||||
int resultbase = base;
|
int resultbase = base;
|
||||||
// Expand the stack if necessary
|
// Expand the stack if necessary
|
||||||
checkstack( c.p.maxstacksize );
|
checkstack( c.p.maxstacksize );
|
||||||
if ( ! c.p.is_vararg ) {
|
if ( c.p.is_vararg == 0 ) {
|
||||||
base += 1;
|
base += 1;
|
||||||
luaV_adjusttop( base+c.p.numparams );
|
luaV_adjusttop( base+c.p.numparams );
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -235,6 +235,9 @@ public class Print extends Lua {
|
|||||||
else
|
else
|
||||||
ps.print(" ; " + ((int) c));
|
ps.print(" ; " + ((int) c));
|
||||||
break;
|
break;
|
||||||
|
case OP_VARARG:
|
||||||
|
ps.print( " ; is_vararg="+ f.is_vararg );
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ public class LuaJit extends Lua implements LuaCompiler {
|
|||||||
// parameters
|
// parameters
|
||||||
int ns = p.maxstacksize;
|
int ns = p.maxstacksize;
|
||||||
int is = 0;
|
int is = 0;
|
||||||
if ( ! p.is_vararg ) {
|
if ( p.is_vararg == 0 ) {
|
||||||
ps.println( "\t\tvm.checkstack("+(p.maxstacksize+1)+");" );
|
ps.println( "\t\tvm.checkstack("+(p.maxstacksize+1)+");" );
|
||||||
ps.println( "\t\tvm.settop("+(p.numparams+1)+");");
|
ps.println( "\t\tvm.settop("+(p.numparams+1)+");");
|
||||||
ps.println( "\t\tint base = vm.base + 1;" );
|
ps.println( "\t\tint base = vm.base + 1;" );
|
||||||
@@ -291,7 +291,7 @@ public class LuaJit extends Lua implements LuaCompiler {
|
|||||||
ps.println();
|
ps.println();
|
||||||
|
|
||||||
// save var args
|
// save var args
|
||||||
if ( p.is_vararg ) {
|
if ( p.is_vararg != 0 ) {
|
||||||
ps.println( "\t\tint ncopy, ntotal;" );
|
ps.println( "\t\tint ncopy, ntotal;" );
|
||||||
ps.println( "\t\tint nvarargs = vm.top - vm.base - 1;" );
|
ps.println( "\t\tint nvarargs = vm.top - vm.base - 1;" );
|
||||||
ps.println( "\t\tint base = vm.base + 1 + nvarargs;" );
|
ps.println( "\t\tint base = vm.base + 1 + nvarargs;" );
|
||||||
@@ -584,7 +584,7 @@ public class LuaJit extends Lua implements LuaCompiler {
|
|||||||
if ( Lua.GET_OPCODE(code[pc-1]) == Lua.OP_RETURN )
|
if ( Lua.GET_OPCODE(code[pc-1]) == Lua.OP_RETURN )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ( p.is_vararg )
|
if ( p.is_vararg != 0 )
|
||||||
ps.println( "\t\tbase -= nvarargs;" );
|
ps.println( "\t\tbase -= nvarargs;" );
|
||||||
else
|
else
|
||||||
ps.println( "\t\tbase -= 1;" );
|
ps.println( "\t\tbase -= 1;" );
|
||||||
|
|||||||
Binary file not shown.
@@ -27,5 +27,5 @@ public class RegressionTests extends AbstractUnitTests {
|
|||||||
public void testControlChars() { doTest("controlchars.lua"); }
|
public void testControlChars() { doTest("controlchars.lua"); }
|
||||||
public void testComparators() { doTest("comparators.lua"); }
|
public void testComparators() { doTest("comparators.lua"); }
|
||||||
public void testMathRandomseed() { doTest("mathrandomseed.lua"); }
|
public void testMathRandomseed() { doTest("mathrandomseed.lua"); }
|
||||||
|
public void testVarargs() { doTest("varargs.lua"); }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,6 +176,10 @@ public class CompatibiltyTest extends ScriptDrivenTest {
|
|||||||
runTest("upvalues3");
|
runTest("upvalues3");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testVarargs() throws IOException, InterruptedException {
|
||||||
|
runTest("varargs");
|
||||||
|
}
|
||||||
|
|
||||||
public void testWeakTable() throws IOException, InterruptedException {
|
public void testWeakTable() throws IOException, InterruptedException {
|
||||||
runTest("weaktable");
|
runTest("weaktable");
|
||||||
}
|
}
|
||||||
|
|||||||
49
src/test/res/varargs.lua
Normal file
49
src/test/res/varargs.lua
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
function p(a,...)
|
||||||
|
print("a",a)
|
||||||
|
print("...",...)
|
||||||
|
print("...,a",...,a)
|
||||||
|
print("a,...",a,...)
|
||||||
|
end
|
||||||
|
--[[ -- these have semantics that depend on compatibity flags
|
||||||
|
function q(a,...)
|
||||||
|
print("a,arg[1],arg[2],arg[3]",a,arg[1],arg[2],arg[3])
|
||||||
|
end
|
||||||
|
function r(a,...)
|
||||||
|
print("a,arg[1],arg[2],arg[3]",a,arg[1],arg[2],arg[3])
|
||||||
|
print("a",a)
|
||||||
|
print("...",...)
|
||||||
|
print("...,a",...,a)
|
||||||
|
print("a,...",a,...)
|
||||||
|
end
|
||||||
|
--]]
|
||||||
|
function s(a)
|
||||||
|
local arg = { '1', '2', '3' }
|
||||||
|
print("a,arg[1],arg[2],arg[3]",a,arg[1],arg[2],arg[3])
|
||||||
|
print("a",a)
|
||||||
|
end
|
||||||
|
function t(a,...)
|
||||||
|
local arg = { '1', '2', '3' }
|
||||||
|
print("a,arg[1],arg[2],arg[3]",a,arg[1],arg[2],arg[3])
|
||||||
|
print("a",a)
|
||||||
|
print("...",...)
|
||||||
|
print("...,a",...,a)
|
||||||
|
print("a,...",a,...)
|
||||||
|
end
|
||||||
|
arg = { "global-1", "global-2", "global-3" }
|
||||||
|
function tryall(f,name)
|
||||||
|
print( '---- function '..name..'()' )
|
||||||
|
print( '--'..name..'():' )
|
||||||
|
print( ' ->', pcall( f ) )
|
||||||
|
print( '--'..name..'("q"):' )
|
||||||
|
print( ' ->', pcall( f, "q" ) )
|
||||||
|
print( '--'..name..'("q","r"):' )
|
||||||
|
print( ' ->', pcall( f, "q", "r" ) )
|
||||||
|
print( '--'..name..'("q","r","s"):' )
|
||||||
|
print( ' ->', pcall( f, "q", "r", "s" ) )
|
||||||
|
end
|
||||||
|
tryall(p,'p')
|
||||||
|
-- tryall(q,'q')
|
||||||
|
-- tryall(r,'r')
|
||||||
|
tryall(s,'s')
|
||||||
|
tryall(t,'t')
|
||||||
Reference in New Issue
Block a user