Improve lua2java code generation.

This commit is contained in:
James Roseborough
2010-07-29 15:10:12 +00:00
parent e3d1330763
commit cd35ad7cbd
4 changed files with 90 additions and 31 deletions

View File

@@ -34,7 +34,7 @@ public class TailcallVarargs extends Varargs {
public TailcallVarargs(LuaValue object, LuaValue methodname, Varargs args) { public TailcallVarargs(LuaValue object, LuaValue methodname, Varargs args) {
this.func = object.get(methodname); this.func = object.get(methodname);
this.args = args; this.args = LuaValue.varargsOf(object, args);
} }
public boolean isTailcall() { public boolean isTailcall() {

View File

@@ -243,7 +243,7 @@ public class JavaCodeGen {
} }
} }
private void multiAssign(List varsOrNames, List<Exp> exps) { private void multiAssign(final List varsOrNames, List<Exp> exps) {
final boolean[] needsTmpvarsMultiAssign = { false }; final boolean[] needsTmpvarsMultiAssign = { false };
if ( exps.size() > 1 ) { if ( exps.size() > 1 ) {
new Visitor() { new Visitor() {
@@ -252,6 +252,7 @@ public class JavaCodeGen {
public void visit(FuncCall exp) { needsTmpvarsMultiAssign[0] = true; } public void visit(FuncCall exp) { needsTmpvarsMultiAssign[0] = true; }
public void visit(IndexExp exp) { needsTmpvarsMultiAssign[0] = true; } public void visit(IndexExp exp) { needsTmpvarsMultiAssign[0] = true; }
public void visit(MethodCall exp) { needsTmpvarsMultiAssign[0] = true; } public void visit(MethodCall exp) { needsTmpvarsMultiAssign[0] = true; }
public void visit(NameExp exp) { needsTmpvarsMultiAssign[0] = true; }
}.visitExps(exps); }.visitExps(exps);
} }
if ( needsTmpvarsMultiAssign[0] ) if ( needsTmpvarsMultiAssign[0] )

View File

@@ -22,7 +22,10 @@
package org.luaj.luajc; package org.luaj.luajc;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.InputStream; import java.io.InputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue; import org.luaj.vm2.LuaValue;
@@ -34,36 +37,69 @@ 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 =
"local a='a\\ab\\bf\\fn\\nt\\tv\\vw\\133x\\222y'\n"+ "for i = 1,2 do\n"+
"local t={string.byte(a,1,#a)}\n"+ " t[i] = function()\n"+
"print( table.concat(t,',') )\n"; " return i\n"+
" end\n"+
"end\n";
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
System.out.println(script); System.out.println(script);
try {
// create an environment to run in
LuaTable _G = JsePlatform.standardGlobals(); // create an environment to run in
LuaTable _G = JsePlatform.standardGlobals();
// compile into a chunk, or load as a class
LuaValue chunk; // compile into a chunk, or load as a class
if ( ! (args.length>0 && args[0].equals("nocompile")) ) { LuaValue chunk;
InputStream is = new ByteArrayInputStream( script.getBytes() ); if ( ! (args.length>0 && args[0].equals("nocompile")) ) {
chunk = LuaJC.getInstance().load(is, "script", _G); InputStream is = new ByteArrayInputStream( script.getBytes() );
} else { chunk = LuaJC.getInstance().load(is, "script", _G);
chunk = (LuaValue) Class.forName("script").newInstance(); } else {
chunk = (LuaValue) Class.forName("script").newInstance();
}
chunk.setfenv(_G);
// call with arguments
LuaValue[] vargs = new LuaValue[args.length];
for ( int i=0; i<args.length; i++ )
vargs[i] = LuaValue.valueOf(args[i]);
Varargs cargs = LuaValue.varargsOf(vargs);
Varargs v = chunk.invoke(cargs);
// print the result
for ( int i=1; i<=v.narg(); i++ )
System.out.println("result["+i+"]: "+v.arg(i));
} catch ( Throwable e ) {
e.printStackTrace();
saveClasses();
} }
chunk.setfenv(_G);
// call with arguments
LuaValue[] vargs = new LuaValue[args.length];
for ( int i=0; i<args.length; i++ )
vargs[i] = LuaValue.valueOf(args[i]);
Varargs cargs = LuaValue.varargsOf(vargs);
Varargs v = chunk.invoke(cargs);
// print the result
for ( int i=1; i<=v.narg(); i++ )
System.out.println("result["+i+"]: "+v.arg(i));
} }
private static void saveClasses() throws Exception {
// create the chunk
String chunkname = "script";
String filename = "script";
String destdir = ".";
InputStream is = new ByteArrayInputStream( script.getBytes() );
Hashtable t = LuaJC.getInstance().compileAll(is, chunkname, filename);
// write out the chunk
for ( Enumeration e = t.keys(); e.hasMoreElements(); ) {
String key = (String) e.nextElement();
byte[] bytes = (byte[]) t.get(key);
String destpath = (destdir!=null? destdir+"/": "") + key + ".class";
System.out.println(
"chunk "+chunkname+
" from "+filename+
" written to "+destpath
+" length="+bytes.length+" bytes");
FileOutputStream fos = new FileOutputStream( destpath );
fos.write( bytes );
fos.close();
}
}
} }

View File

@@ -27,6 +27,7 @@ import java.io.InputStream;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.luaj.vm2.compiler.LuaC; import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lua2java.Lua2Java;
import org.luaj.vm2.luajc.LuaJC; import org.luaj.vm2.luajc.LuaJC;
/** /**
@@ -36,16 +37,27 @@ import org.luaj.vm2.luajc.LuaJC;
*/ */
public class FragmentsTest extends TestCase { public class FragmentsTest extends TestCase {
static final int TEST_TYPE_LUAC = 0;
static final int TEST_TYPE_LUAJC = 1;
static final int TEST_TYPE_LUA2JAVA = 2;
static final int TEST_TYPE = TEST_TYPE_LUA2JAVA;
public void runFragment( Varargs expected, String script ) { public void runFragment( Varargs expected, String script ) {
try { try {
String name = getName(); String name = getName();
LuaTable _G = org.luaj.vm2.lib.JsePlatform.standardGlobals(); LuaTable _G = org.luaj.vm2.lib.JsePlatform.standardGlobals();
InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8")); InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8"));
LuaValue chunk ; LuaValue chunk ;
if ( true ) { 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); chunk = LuaJC.getInstance().load(is,name,_G);
} else { break;
default:
chunk = LuaC.instance.load( is, name, _G ); chunk = LuaC.instance.load( is, name, _G );
break;
} }
Varargs actual = chunk.invoke(); Varargs actual = chunk.invoke();
assertEquals( expected.narg(), actual.narg() ); assertEquals( expected.narg(), actual.narg() );
@@ -135,7 +147,6 @@ public class FragmentsTest extends TestCase {
"local bar = {1000, math.sqrt(9)}\n"+ "local bar = {1000, math.sqrt(9)}\n"+
"return bar[1]+bar[2]\n" ); "return bar[1]+bar[2]\n" );
} }
public void testMultiAssign() { public void testMultiAssign() {
// arargs evaluations are all done before assignments // arargs evaluations are all done before assignments
@@ -339,4 +350,15 @@ public class FragmentsTest extends TestCase {
"local a,b,c = 2,-2.5,0\n" + "local a,b,c = 2,-2.5,0\n" +
"return (a==c), (b==c), (a==a), (a>c), (b>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");
}
} }