Fix compiler varargs support, add tests for varargs compatibility.

This commit is contained in:
James Roseborough
2009-01-28 22:13:27 +00:00
parent 249b711f9f
commit 241f139a68
14 changed files with 79 additions and 32 deletions

View File

@@ -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);

View File

@@ -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() {
}

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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;
}

View File

@@ -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.

View File

@@ -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"); }

View File

@@ -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"); }
}

View File

@@ -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
View 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')