From 241f139a685a15ca7ef60725df31e7e87aa504c8 Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Wed, 28 Jan 2009 22:13:27 +0000 Subject: [PATCH] Fix compiler varargs support, add tests for varargs compatibility. --- src/core/org/luaj/compiler/DumpState.java | 2 +- src/core/org/luaj/compiler/FuncState.java | 1 - src/core/org/luaj/compiler/LexState.java | 21 +++----- src/core/org/luaj/compiler/LuaC.java | 3 +- src/core/org/luaj/vm/LPrototype.java | 2 +- src/core/org/luaj/vm/LoadState.java | 2 +- src/core/org/luaj/vm/LuaState.java | 2 +- src/core/org/luaj/vm/Print.java | 3 ++ src/script/org/luaj/jit/LuaJit.java | 6 +-- src/test/compile/regressions.zip | Bin 3137 -> 4055 bytes .../org/luaj/compiler/CompilerUnitTests.java | 2 +- .../org/luaj/compiler/RegressionTests.java | 14 ++--- .../java/org/luaj/vm/CompatibiltyTest.java | 4 ++ src/test/res/varargs.lua | 49 ++++++++++++++++++ 14 files changed, 79 insertions(+), 32 deletions(-) create mode 100644 src/test/res/varargs.lua diff --git a/src/core/org/luaj/compiler/DumpState.java b/src/core/org/luaj/compiler/DumpState.java index 7ff5c970..a9ddd59e 100644 --- a/src/core/org/luaj/compiler/DumpState.java +++ b/src/core/org/luaj/compiler/DumpState.java @@ -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); diff --git a/src/core/org/luaj/compiler/FuncState.java b/src/core/org/luaj/compiler/FuncState.java index a9fdf870..16d05539 100644 --- a/src/core/org/luaj/compiler/FuncState.java +++ b/src/core/org/luaj/compiler/FuncState.java @@ -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() { } diff --git a/src/core/org/luaj/compiler/LexState.java b/src/core/org/luaj/compiler/LexState.java index c34d5697..420e2df9 100644 --- a/src/core/org/luaj/compiler/LexState.java +++ b/src/core/org/luaj/compiler/LexState.java @@ -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(" 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; } diff --git a/src/core/org/luaj/compiler/LuaC.java b/src/core/org/luaj/compiler/LuaC.java index 094499a1..f72031ef 100644 --- a/src/core/org/luaj/compiler/LuaC.java +++ b/src/core/org/luaj/compiler/LuaC.java @@ -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(); diff --git a/src/core/org/luaj/vm/LPrototype.java b/src/core/org/luaj/vm/LPrototype.java index 3cb3eca9..2581e996 100644 --- a/src/core/org/luaj/vm/LPrototype.java +++ b/src/core/org/luaj/vm/LPrototype.java @@ -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; } diff --git a/src/core/org/luaj/vm/LoadState.java b/src/core/org/luaj/vm/LoadState.java index 1b93d01a..1304a404 100644 --- a/src/core/org/luaj/vm/LoadState.java +++ b/src/core/org/luaj/vm/LoadState.java @@ -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); diff --git a/src/core/org/luaj/vm/LuaState.java b/src/core/org/luaj/vm/LuaState.java index df93267c..0a9663e5 100644 --- a/src/core/org/luaj/vm/LuaState.java +++ b/src/core/org/luaj/vm/LuaState.java @@ -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 { diff --git a/src/core/org/luaj/vm/Print.java b/src/core/org/luaj/vm/Print.java index 72a143f7..31b47ce7 100644 --- a/src/core/org/luaj/vm/Print.java +++ b/src/core/org/luaj/vm/Print.java @@ -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; } diff --git a/src/script/org/luaj/jit/LuaJit.java b/src/script/org/luaj/jit/LuaJit.java index 1ff499ba..5542b786 100644 --- a/src/script/org/luaj/jit/LuaJit.java +++ b/src/script/org/luaj/jit/LuaJit.java @@ -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;" ); diff --git a/src/test/compile/regressions.zip b/src/test/compile/regressions.zip index 76e431d93cdce4b507fe15b1f9c49f67c426053e..1db47c12596a90c751128ada1f4504c5e977ae09 100644 GIT binary patch delta 957 zcmX>oab13c5Jx>TiwFY)0|&$AY#Xani6+IZKwb?K1A{n_E=o-=N-ZwV%+D*E9gS0Gv@ZsDgS>clwp) ziHlYVX&ue9yv<(pK+;0-qnw#gWtW}zks9mS7Lj2KncRNb7+cT2J2U^-z53d@dlmZ@ zY4laOOnI_+bB&4I{Q4ad`~OUN8d+y1w{QQs6%!S1Oi7Qw(CFvF{i`*@alcTk;yIyo zs|8I_oAkM!6s~+#zj#&5)rhN8Z?Yvi-j+zLcE6JDI5*=#cF=~8PgjW_+y3#?k2x=* z60Ut<|JnOypR1O|A0zwyJ1)&O?otXo{4l^diO0xvGh>*dhf0BfRfkPR<%Kva=b3l6 z?QVV7YA?QF4`Z`+q0j1)Ia5S^mweN_u3`9P>W=PW_M%U>4+k&q3z4m#e~BmL{DfmV zTecsqXE2I9EBjOT`Mrg1?>KfDSoD0)sC_4uy!`B&Ei-L%`RcNbH~q2Z%d;0;kzUOE z&T7Z=2m9FhZC*?|Z4q}R^;q?l6Vo0D@+_11rmeL@B~|vAwL!G0{&CN!%S+Z|M%~s6 z;a&XVP?K*={fbu}S3m9#v^igPySaX@X~heMtLr{pUfMQ)+SliwB0li2wM(COtre`x z+MyY!^`~a?topD=#=^^TCM~nk4bJ=T@zd?c#fXF?^Ur%T6PEcuO8Il?M+_*8vi_bg z-_5@#N$a2e`t1_2BKuw+oNW5S@<#E7_XmUd9qcyc-YRui{dmut?Q8fCdbe5yn7Rq^ z%g@q#>CWc7A=N*A%Z*d|n*}&zS?U>?M7VKh3t;kMU}R7Lk^&q!Gf99q!Vqi;6l4ek g*pO2ghA6Je?0L*oa+5i9m delta 33 jcmcaEe^6qB5XWX&ZfO<~RyGD8;0Ho!76t|Z4iFCjZ!rW2 diff --git a/src/test/java/org/luaj/compiler/CompilerUnitTests.java b/src/test/java/org/luaj/compiler/CompilerUnitTests.java index 1923e50b..74abda2d 100644 --- a/src/test/java/org/luaj/compiler/CompilerUnitTests.java +++ b/src/test/java/org/luaj/compiler/CompilerUnitTests.java @@ -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"); } diff --git a/src/test/java/org/luaj/compiler/RegressionTests.java b/src/test/java/org/luaj/compiler/RegressionTests.java index c6018389..f36cc027 100644 --- a/src/test/java/org/luaj/compiler/RegressionTests.java +++ b/src/test/java/org/luaj/compiler/RegressionTests.java @@ -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"); } } diff --git a/src/test/java/org/luaj/vm/CompatibiltyTest.java b/src/test/java/org/luaj/vm/CompatibiltyTest.java index 40f3fedb..69d1672c 100644 --- a/src/test/java/org/luaj/vm/CompatibiltyTest.java +++ b/src/test/java/org/luaj/vm/CompatibiltyTest.java @@ -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"); } diff --git a/src/test/res/varargs.lua b/src/test/res/varargs.lua new file mode 100644 index 00000000..370d3ccd --- /dev/null +++ b/src/test/res/varargs.lua @@ -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')