Update bytecode-to-bytecode compiler to handle upvalues in numeric for loops.

This commit is contained in:
James Roseborough
2010-07-29 21:28:13 +00:00
parent cd35ad7cbd
commit dce6007569
7 changed files with 372 additions and 323 deletions

View File

@@ -457,7 +457,6 @@ and LuaForge:
<li>tail calls are not tracked in debug information <li>tail calls are not tracked in debug information
<li>using both version 1 and 2 libraries together in the same java vm has not been tested <li>using both version 1 and 2 libraries together in the same java vm has not been tested
<li>module() and setfenv() only partially supported for lau2java or luajc compiled lua <li>module() and setfenv() only partially supported for lau2java or luajc compiled lua
<li>luajc can produce invalid class files in some cases
<li>values associated with weak keys may linger longer than expected <li>values associated with weak keys may linger longer than expected
</ul> </ul>

View File

@@ -355,6 +355,17 @@ public class JavaBuilder {
} }
} }
} }
public void convertToUpvalue(int pc, int slot) {
boolean isupassign = slots.isUpvalueAssign(pc, slot);
if ( isupassign ) {
int index = findSlotIndex( slot, false );
append(new ALOAD(index));
append(factory.createInvoke(classname, "newupl", TYPE_LOCALUPVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKESTATIC));
int upindex = findSlotIndex( slot, true );
append(new ASTORE(upindex));
}
}
private static String upvalueName(int upindex) { private static String upvalueName(int upindex) {
return PREFIX_UPVALUE+upindex; return PREFIX_UPVALUE+upindex;

View File

@@ -60,7 +60,7 @@ public class JavaGen {
for ( int pc=0, n=p.code.length; pc<n; pc++ ) { for ( int pc=0, n=p.code.length; pc<n; pc++ ) {
int pc0 = pc; // closure changes pc int pc0 = pc; // closure changes pc
int ins = p.code[pc]; int ins = p.code[pc];
int o = Lua.GET_OPCODE(ins); final int o = Lua.GET_OPCODE(ins);
int a = Lua.GETARG_A(ins); int a = Lua.GETARG_A(ins);
int b = Lua.GETARG_B(ins); int b = Lua.GETARG_B(ins);
int bx = Lua.GETARG_Bx(ins); int bx = Lua.GETARG_Bx(ins);
@@ -410,6 +410,13 @@ public class JavaGen {
// let builder process branch instructions // let builder process branch instructions
builder.onEndOfLuaInstruction( pc0 ); builder.onEndOfLuaInstruction( pc0 );
// for-loops have upvalue created at top of loop
switch ( o ) {
case Lua.OP_FORPREP:
builder.convertToUpvalue(pc+1, a+3);
break;
}
} }
} }

View File

@@ -37,10 +37,11 @@ public class TestLuaJC {
// create the script // create the script
public static String name = "script"; public static String name = "script";
public static String script = public static String script =
"for i = 1,2 do\n"+ "for i = 1,2 do\n" +
" t[i] = function()\n"+ " i = i + 5\n"+
" return (function()\n"+
" return i\n"+ " return i\n"+
" end\n"+ " end)()\n"+
"end\n"; "end\n";
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {

View File

@@ -58,6 +58,10 @@ public class AllTests {
table.addTestSuite(WeakKeyValueTableTest.class); table.addTestSuite(WeakKeyValueTableTest.class);
suite.addTest(table); suite.addTest(table);
// bytecode compilers regression tests
TestSuite bytecodetests = FragmentsTest.suite();
suite.addTest(bytecodetests);
// prototype compiler // prototype compiler
TestSuite compiler = new TestSuite("Lua Compiler Tests"); TestSuite compiler = new TestSuite("Lua Compiler Tests");
compiler.addTestSuite(CompilerUnitTests.class); compiler.addTestSuite(CompilerUnitTests.class);
@@ -73,16 +77,11 @@ public class AllTests {
suite.addTest(lib); suite.addTest(lib);
// compatiblity tests // compatiblity tests
TestSuite compat = (TestSuite) CompatibiltyTest.suite(); TestSuite compat = CompatibiltyTest.suite();
suite.addTest( compat ); suite.addTest( compat );
compat.addTestSuite(ErrorsTest.class); compat.addTestSuite(ErrorsTest.class);
compat.addTestSuite(Luajvm1CompatibilityTest.class); compat.addTestSuite(Luajvm1CompatibilityTest.class);
// luajc regression tests
TestSuite luajc = new TestSuite("Java Compiler Tests");
luajc.addTestSuite(FragmentsTest.class);
suite.addTest(luajc);
return suite; return suite;
} }

View File

@@ -59,11 +59,11 @@ public class CompatibiltyTest {
} }
public static Test suite() { public static TestSuite suite() {
TestSuite suite = new TestSuite("Compatibility Tests"); TestSuite suite = new TestSuite("Compatibility Tests");
suite.addTest( new TestSuite( JseCompatibilityTest.class, "JSE Tests" ) ); suite.addTest( new TestSuite( JseCompatibilityTest.class, "JSE Tests" ) );
suite.addTest( new TestSuite( JmeCompatibilityTest.class, "JME Tests" ) ); suite.addTest( new TestSuite( JmeCompatibilityTest.class, "JME Tests" ) );
suite.addTest( new TestSuite( JseBytecodeTest.class, "JSE Bytecode Tests" ) ); suite.addTest( new TestSuite( LuaJCTest.class, "JSE Bytecode Tests" ) );
suite.addTest( new TestSuite( Lua2JavaTest.class, "Lua2Java Tests" ) ); suite.addTest( new TestSuite( Lua2JavaTest.class, "Lua2Java Tests" ) );
return suite; return suite;
} }
@@ -74,7 +74,7 @@ public class CompatibiltyTest {
} }
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp(); super.setUp();
System.setProperty("Lua2Java", "false"); System.setProperty("JME", "false");
Lua2Java.install(); Lua2Java.install();
} }
} }
@@ -97,8 +97,8 @@ public class CompatibiltyTest {
System.setProperty("JME", "false"); System.setProperty("JME", "false");
} }
} }
public static class JseBytecodeTest extends CompatibiltyTestSuite { public static class LuaJCTest extends CompatibiltyTestSuite {
public JseBytecodeTest() { public LuaJCTest() {
super(ScriptDrivenTest.PlatformType.LUAJIT); super(ScriptDrivenTest.PlatformType.LUAJIT);
} }
protected void setUp() throws Exception { protected void setUp() throws Exception {

View File

@@ -24,8 +24,14 @@ package org.luaj.vm2;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.InputStream; import java.io.InputStream;
import junit.framework.Test;
import junit.framework.TestCase; import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.luaj.vm2.CompatibiltyTest.JmeCompatibilityTest;
import org.luaj.vm2.CompatibiltyTest.JseCompatibilityTest;
import org.luaj.vm2.CompatibiltyTest.Lua2JavaTest;
import org.luaj.vm2.CompatibiltyTest.LuaJCTest;
import org.luaj.vm2.compiler.LuaC; import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lua2java.Lua2Java; import org.luaj.vm2.lua2java.Lua2Java;
import org.luaj.vm2.luajc.LuaJC; import org.luaj.vm2.luajc.LuaJC;
@@ -35,330 +41,356 @@ import org.luaj.vm2.luajc.LuaJC;
* caused problems for jit compiling during development. * caused problems for jit compiling during development.
* *
*/ */
public class FragmentsTest extends TestCase { public class FragmentsTest extends TestSuite {
static final int TEST_TYPE_LUAC = 0; static final int TEST_TYPE_LUAC = 0;
static final int TEST_TYPE_LUAJC = 1; static final int TEST_TYPE_LUAJC = 1;
static final int TEST_TYPE_LUA2JAVA = 2; static final int TEST_TYPE_LUA2JAVA = 2;
static final int TEST_TYPE = TEST_TYPE_LUA2JAVA;
public void runFragment( Varargs expected, String script ) {
try {
String name = getName();
LuaTable _G = org.luaj.vm2.lib.JsePlatform.standardGlobals();
InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8"));
LuaValue chunk ;
switch ( TEST_TYPE ) {
case TEST_TYPE_LUA2JAVA:
chunk = Lua2Java.instance.load(is,name,_G);
break;
case TEST_TYPE_LUAJC:
chunk = LuaJC.getInstance().load(is,name,_G);
break;
default:
chunk = LuaC.instance.load( is, name, _G );
break;
}
Varargs actual = chunk.invoke();
assertEquals( expected.narg(), actual.narg() );
for ( int i=1; i<=actual.narg(); i++ )
assertEquals( expected.arg(i), actual.arg(i) );
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
fail(e.toString());
}
}
public void testForloopParamUpvalues() {
runFragment( LuaValue.varargsOf(new LuaValue[] {
LuaValue.valueOf(77),
LuaValue.valueOf(1) } ),
"for n,p in ipairs({77}) do\n"+
" print('n,p',n,p)\n"+
" foo = function()\n"+
" return p,n\n"+
" end\n"+
" return foo()\n"+
"end\n");
}
public void testVarVarargsUseArg() { public static class JseFragmentsTest extends FragmentsTestCase {
runFragment( LuaValue.varargsOf( new LuaValue[] { public JseFragmentsTest() { super( TEST_TYPE_LUAC ); }
LuaValue.valueOf("a"),
LuaValue.valueOf(2),
LuaValue.valueOf("b"),
LuaValue.valueOf("c"),
LuaValue.NIL }),
"function q(a,...)\n" +
" return a,arg.n,arg[1],arg[2],arg[3]\n" +
"end\n" +
"return q('a','b','c')\n" );
} }
public static class LuaJCFragmentsTest extends FragmentsTestCase {
public LuaJCFragmentsTest() { super( TEST_TYPE_LUAJC ); }
}
public static class Lua2JavaFragmentsTest extends FragmentsTestCase {
public Lua2JavaFragmentsTest() { super( TEST_TYPE_LUA2JAVA ); }
}
public static TestSuite suite() {
TestSuite suite = new TestSuite("Compiler Fragments Tests");
suite.addTest( new TestSuite( JseFragmentsTest.class, "JSE Fragments Tests" ) );
suite.addTest( new TestSuite( LuaJCFragmentsTest.class, "LuaJC Fragments Tests" ) );
suite.addTest( new TestSuite( Lua2JavaFragmentsTest.class, "Lua2Java Fragments Tests" ) );
return suite;
}
abstract protected static class FragmentsTestCase extends TestCase {
final int TEST_TYPE;
public void testVarVarargsUseBoth() { protected FragmentsTestCase(int testType) {
runFragment( LuaValue.varargsOf( new LuaValue[] { this.TEST_TYPE = testType;
LuaValue.valueOf("a"), }
LuaValue.valueOf("nil"),
LuaValue.valueOf("b"),
LuaValue.valueOf("c")}),
"function r(a,...)\n" +
" return a,type(arg),...\n" +
"end\n" +
"return r('a','b','c')\n" );
}
public void testArgVarargsUseBoth() {
runFragment( LuaValue.varargsOf( new LuaValue[] {
LuaValue.NIL,
LuaValue.valueOf("b"),
LuaValue.valueOf("c")}),
"function v(arg,...)\n" +
" return arg,...\n" +
"end\n" +
"return v('a','b','c')\n" );
}
public void testArgParamUseNone() { public void runFragment( Varargs expected, String script ) {
// the name "arg" is treated specially, and ends up masking the argument value in 5.1 try {
runFragment( LuaValue.valueOf("table"), String name = getName();
"function v(arg,...)\n" + LuaTable _G = org.luaj.vm2.lib.JsePlatform.standardGlobals();
" return type(arg)\n" + InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8"));
"end\n" + LuaValue chunk ;
"return v('abc')\n" ); switch ( TEST_TYPE ) {
} case TEST_TYPE_LUA2JAVA:
chunk = Lua2Java.instance.load(is,name,_G);
public void testSetlistVarargs() { break;
runFragment( LuaValue.valueOf("abc"), case TEST_TYPE_LUAJC:
"local f = function() return 'abc' end\n" + chunk = LuaJC.getInstance().load(is,name,_G);
"local g = { f() }\n" + break;
"return g[1]\n" ); default:
} chunk = LuaC.instance.load( is, name, _G );
break;
public void testSelfOp() { }
runFragment( LuaValue.valueOf("bcd"), Varargs actual = chunk.invoke();
"local s = 'abcde'\n"+ assertEquals( expected.narg(), actual.narg() );
"return s:sub(2,4)\n" ); for ( int i=1; i<=actual.narg(); i++ )
} assertEquals( expected.arg(i), actual.arg(i) );
} catch (Exception e) {
public void testSetListWithOffsetAndVarargs() { // TODO Auto-generated catch block
runFragment( LuaValue.valueOf(1003), e.printStackTrace();
"local bar = {1000, math.sqrt(9)}\n"+ fail(e.toString());
"return bar[1]+bar[2]\n" ); }
} }
public void testMultiAssign() {
// arargs evaluations are all done before assignments
runFragment( LuaValue.varargsOf(new LuaValue[]{
LuaValue.valueOf(111),
LuaValue.valueOf(111),
LuaValue.valueOf(111)}),
"a,b,c = 1,10,100\n" +
"a,b,c = a+b+c, a+b+c, a+b+c\n" +
"return a,b,c\n" );
}
public void testUpvalues() {
runFragment( LuaValue.valueOf(999),
"local a = function(x)\n" +
" return function(y)\n" +
" return x + y\n" +
" end\n" +
"end\n" +
"local b = a(222)\n" +
"local c = b(777)\n" +
"print( 'c=', c )\n" +
"return c\n" );
}
public void testNeedsArgAndHasArg() {
runFragment( LuaValue.varargsOf(LuaValue.valueOf(333),LuaValue.NIL,LuaValue.valueOf(222)),
"function r(q,...)\n"+
" local a=arg\n"+
" return a and a[2]\n"+
"end\n" +
"function s(q,...)\n"+
" local a=arg\n"+
" local b=...\n"+
" return a and a[2],b\n"+
"end\n" +
"return r(111,222,333),s(111,222,333)" );
} public void testForloopParamUpvalues() {
runFragment( LuaValue.varargsOf(new LuaValue[] {
LuaValue.valueOf(77),
LuaValue.valueOf(1) } ),
"for n,p in ipairs({77}) do\n"+
" print('n,p',n,p)\n"+
" foo = function()\n"+
" return p,n\n"+
" end\n"+
" return foo()\n"+
"end\n");
}
public void testNonAsciiStringLiterals() { public void testVarVarargsUseArg() {
runFragment( LuaValue.valueOf("7,8,12,10,9,11,133,222"), runFragment( LuaValue.varargsOf( new LuaValue[] {
"local a='\\a\\b\\f\\n\\t\\v\\133\\222'\n"+ LuaValue.valueOf("a"),
"local t={string.byte(a,1,#a)}\n"+ LuaValue.valueOf(2),
"return table.concat(t,',')\n" ); LuaValue.valueOf("b"),
} LuaValue.valueOf("c"),
LuaValue.NIL }),
public void testControlCharStringLiterals() { "function q(a,...)\n" +
runFragment( LuaValue.valueOf("97,0,98,18,99,18,100,18,48,101"), " return a,arg.n,arg[1],arg[2],arg[3]\n" +
"local a='a\\0b\\18c\\018d\\0180e'\n"+
"local t={string.byte(a,1,#a)}\n"+
"return table.concat(t,',')\n" );
}
public void testLoopVarNames() {
runFragment( LuaValue.valueOf(" 234,1,aa 234,2,bb"),
"local w = ''\n"+
"function t()\n"+
" for f,var in ipairs({'aa','bb'}) do\n"+
" local s = 234\n"+
" w = w..' '..s..','..f..','..var\n"+
" end\n"+
"end\n" +
"t()\n" +
"return w\n" );
}
public void testForLoops() {
runFragment( LuaValue.valueOf("12345 357 963"),
"local s,t,u = '','',''\n"+
"for m=1,5 do\n"+
" s = s..m\n"+
"end\n"+
"for m=3,7,2 do\n"+
" t = t..m\n"+
"end\n"+
"for m=9,3,-3 do\n"+
" u = u..m\n"+
"end\n"+
"return s..' '..t..' '..u\n" );
}
public void testLocalFunctionDeclarations() {
runFragment( LuaValue.varargsOf(LuaValue.valueOf("function"),LuaValue.valueOf("nil")),
"local function aaa()\n"+
" return type(aaa)\n"+
"end\n"+
"local bbb = function()\n"+
" return type(bbb)\n"+
"end\n"+
"return aaa(),bbb()\n" );
}
public void testNilsInTableConstructor() {
runFragment( LuaValue.valueOf("1=111 2=222 3=333 "),
"local t = { 111, 222, 333, nil, nil }\n"+
"local s = ''\n"+
"for i,v in ipairs(t) do \n" +
" s=s..tostring(i)..'='..tostring(v)..' '\n" +
"end\n"+
"return s\n" );
}
public void testUnreachableCode() {
runFragment( LuaValue.valueOf(66),
"local function foo(x) return x * 2 end\n" +
"local function bar(x, y)\n" +
" if x==y then\n" +
" return y\n" +
" else\n" +
" return foo(x)\n" +
" end\n" +
"end\n" +
"return bar(33,44)\n" );
}
public void testVarargsWithParameters() {
runFragment( LuaValue.valueOf(222),
"local func = function(t,...)\n"+
" return (...)\n"+
"end\n"+
"return func(111,222,333)\n" );
}
public void testNoReturnValuesPlainCall() {
runFragment( LuaValue.TRUE,
"local testtable = {}\n"+
"return pcall( function() testtable[1]=2 end )\n" );
}
public void testVarargsInTableConstructor() {
runFragment( LuaValue.valueOf(222),
"local function foo() return 111,222,333 end\n"+
"local t = {'a','b',c='c',foo()}\n"+
"return t[4]\n" );
}
public void testVarargsInFirstArg() {
runFragment( LuaValue.valueOf(123),
"function aaa(x) return x end\n" +
"function bbb(y) return y end\n" +
"function ccc(z) return z end\n" +
"return ccc( aaa(bbb(123)), aaa(456) )\n" );
}
public void testSetUpvalueTableInitializer() {
runFragment( LuaValue.valueOf("b"),
"local aliases = {a='b'}\n" +
"local foo = function()\n" +
" return aliases\n" +
"end\n" + "end\n" +
"return foo().a\n" ); "return q('a','b','c')\n" );
} }
public void testVarVarargsUseBoth() {
public void testLoadNilUpvalue() { runFragment( LuaValue.varargsOf( new LuaValue[] {
runFragment( LuaValue.NIL, LuaValue.valueOf("a"),
"tostring = function() end\n" + LuaValue.valueOf("nil"),
"local pc \n" + LuaValue.valueOf("b"),
"local pcall = function(...)\n" + LuaValue.valueOf("c")}),
" pc(...)\n" + "function r(a,...)\n" +
" return a,type(arg),...\n" +
"end\n" + "end\n" +
"return NIL\n" ); "return r('a','b','c')\n" );
} }
public void testUpvalueClosure() { public void testArgVarargsUseBoth() {
runFragment( LuaValue.NIL, runFragment( LuaValue.varargsOf( new LuaValue[] {
"print()\n"+ LuaValue.NIL,
"local function f2() end\n"+ LuaValue.valueOf("b"),
"local function f3()\n"+ LuaValue.valueOf("c")}),
" return f3\n"+ "function v(arg,...)\n" +
" return arg,...\n" +
"end\n" + "end\n" +
"return NIL\n" ); "return v('a','b','c')\n" );
} }
public void testUninitializedUpvalue() { public void testArgParamUseNone() {
runFragment( LuaValue.NIL, // the name "arg" is treated specially, and ends up masking the argument value in 5.1
"local f\n"+ runFragment( LuaValue.valueOf("table"),
"do\n"+ "function v(arg,...)\n" +
" function g()\n"+ " return type(arg)\n" +
" print(f())\n"+ "end\n" +
"return v('abc')\n" );
}
public void testSetlistVarargs() {
runFragment( LuaValue.valueOf("abc"),
"local f = function() return 'abc' end\n" +
"local g = { f() }\n" +
"return g[1]\n" );
}
public void testSelfOp() {
runFragment( LuaValue.valueOf("bcd"),
"local s = 'abcde'\n"+
"return s:sub(2,4)\n" );
}
public void testSetListWithOffsetAndVarargs() {
runFragment( LuaValue.valueOf(1003),
"local bar = {1000, math.sqrt(9)}\n"+
"return bar[1]+bar[2]\n" );
}
public void testMultiAssign() {
// arargs evaluations are all done before assignments
runFragment( LuaValue.varargsOf(new LuaValue[]{
LuaValue.valueOf(111),
LuaValue.valueOf(111),
LuaValue.valueOf(111)}),
"a,b,c = 1,10,100\n" +
"a,b,c = a+b+c, a+b+c, a+b+c\n" +
"return a,b,c\n" );
}
public void testUpvalues() {
runFragment( LuaValue.valueOf(999),
"local a = function(x)\n" +
" return function(y)\n" +
" return x + y\n" +
" end\n" +
"end\n" +
"local b = a(222)\n" +
"local c = b(777)\n" +
"print( 'c=', c )\n" +
"return c\n" );
}
public void testNeedsArgAndHasArg() {
runFragment( LuaValue.varargsOf(LuaValue.valueOf(333),LuaValue.NIL,LuaValue.valueOf(222)),
"function r(q,...)\n"+
" local a=arg\n"+
" return a and a[2]\n"+
"end\n" +
"function s(q,...)\n"+
" local a=arg\n"+
" local b=...\n"+
" return a and a[2],b\n"+
"end\n" +
"return r(111,222,333),s(111,222,333)" );
}
public void testNonAsciiStringLiterals() {
runFragment( LuaValue.valueOf("7,8,12,10,9,11,133,222"),
"local a='\\a\\b\\f\\n\\t\\v\\133\\222'\n"+
"local t={string.byte(a,1,#a)}\n"+
"return table.concat(t,',')\n" );
}
public void testControlCharStringLiterals() {
runFragment( LuaValue.valueOf("97,0,98,18,99,18,100,18,48,101"),
"local a='a\\0b\\18c\\018d\\0180e'\n"+
"local t={string.byte(a,1,#a)}\n"+
"return table.concat(t,',')\n" );
}
public void testLoopVarNames() {
runFragment( LuaValue.valueOf(" 234,1,aa 234,2,bb"),
"local w = ''\n"+
"function t()\n"+
" for f,var in ipairs({'aa','bb'}) do\n"+
" local s = 234\n"+
" w = w..' '..s..','..f..','..var\n"+
" end\n"+ " end\n"+
"end\n" + "end\n" +
"return NIL\n" ); "t()\n" +
} "return w\n" );
public void testTestOpUpvalues() { }
runFragment( LuaValue.varargsOf(LuaValue.valueOf(1),LuaValue.valueOf(2),LuaValue.valueOf(3)),
"print( nil and 'T' or 'F' )\n"+ public void testForLoops() {
"local a,b,c = 1,2,3\n"+ runFragment( LuaValue.valueOf("12345 357 963"),
"function foo()\n"+ "local s,t,u = '','',''\n"+
" return a,b,c\n"+ "for m=1,5 do\n"+
"end\n" + " s = s..m\n"+
"return foo()\n" ); "end\n"+
} "for m=3,7,2 do\n"+
public void testTestSimpleBinops() { " t = t..m\n"+
runFragment( LuaValue.varargsOf(new LuaValue[] { "end\n"+
LuaValue.FALSE, LuaValue.FALSE, LuaValue.TRUE, LuaValue.TRUE, LuaValue.FALSE }), "for m=9,3,-3 do\n"+
"local a,b,c = 2,-2.5,0\n" + " u = u..m\n"+
"return (a==c), (b==c), (a==a), (a>c), (b>0)\n" ); "end\n"+
} "return s..' '..t..' '..u\n" );
}
public void testLocalFunctionDeclarations() {
runFragment( LuaValue.varargsOf(LuaValue.valueOf("function"),LuaValue.valueOf("nil")),
"local function aaa()\n"+
" return type(aaa)\n"+
"end\n"+
"local bbb = function()\n"+
" return type(bbb)\n"+
"end\n"+
"return aaa(),bbb()\n" );
}
public void testNilsInTableConstructor() {
runFragment( LuaValue.valueOf("1=111 2=222 3=333 "),
"local t = { 111, 222, 333, nil, nil }\n"+
"local s = ''\n"+
"for i,v in ipairs(t) do \n" +
" s=s..tostring(i)..'='..tostring(v)..' '\n" +
"end\n"+
"return s\n" );
}
public void testUnreachableCode() {
runFragment( LuaValue.valueOf(66),
"local function foo(x) return x * 2 end\n" +
"local function bar(x, y)\n" +
" if x==y then\n" +
" return y\n" +
" else\n" +
" return foo(x)\n" +
" end\n" +
"end\n" +
"return bar(33,44)\n" );
}
public void testVarargsWithParameters() {
runFragment( LuaValue.valueOf(222),
"local func = function(t,...)\n"+
" return (...)\n"+
"end\n"+
"return func(111,222,333)\n" );
}
public void testNoReturnValuesPlainCall() {
runFragment( LuaValue.TRUE,
"local testtable = {}\n"+
"return pcall( function() testtable[1]=2 end )\n" );
}
public void testVarargsInTableConstructor() {
runFragment( LuaValue.valueOf(222),
"local function foo() return 111,222,333 end\n"+
"local t = {'a','b',c='c',foo()}\n"+
"return t[4]\n" );
}
public void testNumericForUpvalues() { public void testVarargsInFirstArg() {
runFragment( LuaValue.valueOf(8), runFragment( LuaValue.valueOf(123),
"for i = 3,4 do\n"+ "function aaa(x) return x end\n" +
" i = i + 5\n"+ "function bbb(y) return y end\n" +
" local a = function()\n"+ "function ccc(z) return z end\n" +
" return i\n"+ "return ccc( aaa(bbb(123)), aaa(456) )\n" );
" end\n" + }
" return a()\n"+
"end\n"); public void testSetUpvalueTableInitializer() {
runFragment( LuaValue.valueOf("b"),
"local aliases = {a='b'}\n" +
"local foo = function()\n" +
" return aliases\n" +
"end\n" +
"return foo().a\n" );
}
public void testLoadNilUpvalue() {
runFragment( LuaValue.NIL,
"tostring = function() end\n" +
"local pc \n" +
"local pcall = function(...)\n" +
" pc(...)\n" +
"end\n" +
"return NIL\n" );
}
public void testUpvalueClosure() {
runFragment( LuaValue.NIL,
"print()\n"+
"local function f2() end\n"+
"local function f3()\n"+
" return f3\n"+
"end\n" +
"return NIL\n" );
}
public void testUninitializedUpvalue() {
runFragment( LuaValue.NIL,
"local f\n"+
"do\n"+
" function g()\n"+
" print(f())\n"+
" end\n"+
"end\n" +
"return NIL\n" );
}
public void testTestOpUpvalues() {
runFragment( LuaValue.varargsOf(LuaValue.valueOf(1),LuaValue.valueOf(2),LuaValue.valueOf(3)),
"print( nil and 'T' or 'F' )\n"+
"local a,b,c = 1,2,3\n"+
"function foo()\n"+
" return a,b,c\n"+
"end\n" +
"return foo()\n" );
}
public void testTestSimpleBinops() {
runFragment( LuaValue.varargsOf(new LuaValue[] {
LuaValue.FALSE, LuaValue.FALSE, LuaValue.TRUE, LuaValue.TRUE, LuaValue.FALSE }),
"local a,b,c = 2,-2.5,0\n" +
"return (a==c), (b==c), (a==a), (a>c), (b>0)\n" );
}
public void testNumericForUpvalues() {
runFragment( LuaValue.valueOf(8),
"for i = 3,4 do\n"+
" i = i + 5\n"+
" local a = function()\n"+
" return i\n"+
" end\n" +
" return a()\n"+
"end\n");
}
} }
} }