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