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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -8,7 +8,7 @@ public class CompilerUnitTests extends AbstractUnitTests {
super("src/test/compile/lua5.1-tests.zip", "lua5.1-tests"); 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 testApi() { doTest("api.lua"); }
public void testAttrib() { doTest("attrib.lua"); } public void testAttrib() { doTest("attrib.lua"); }
public void testBig() { doTest("big.lua"); } public void testBig() { doTest("big.lua"); }

View File

@@ -21,11 +21,11 @@ public class RegressionTests extends AbstractUnitTests {
"regressions" ); "regressions" );
} }
public void testModulo() { doTest("modulo.lua"); } public void testModulo() { doTest("modulo.lua"); }
public void testConstruct() { doTest("construct.lua"); } public void testConstruct() { doTest("construct.lua"); }
public void testBigAttrs() { doTest("bigattr.lua"); } public void testBigAttrs() { doTest("bigattr.lua"); }
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"); }
} }

View File

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