Fix vararg parameter handling, self and setlist bytecode processing.
This commit is contained in:
@@ -310,7 +310,8 @@ public class LuaValue extends Varargs {
|
||||
}
|
||||
|
||||
// table initializers
|
||||
public static LuaTable tableOf() { return new LuaTable(); }
|
||||
public static LuaTable tableOf() { return new LuaTable(); }
|
||||
public static LuaTable tableOf(Varargs varargs, int firstarg) { return new LuaTable(varargs.subargs(firstarg)); }
|
||||
public static LuaTable tableOf(int narray, int nhash) { return new LuaTable(narray, nhash); }
|
||||
public static LuaTable listOf(LuaValue[] unnamedValues) { return new LuaTable(null,unnamedValues,null); }
|
||||
public static LuaTable listOf(LuaValue[] unnamedValues,Varargs lastarg) { return new LuaTable(null,unnamedValues,lastarg); }
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.io.InputStream;
|
||||
import org.luaj.vm2.LoadState;
|
||||
import org.luaj.vm2.LuaClosure;
|
||||
import org.luaj.vm2.LuaFunction;
|
||||
import org.luaj.vm2.LuaTable;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.Prototype;
|
||||
import org.luaj.vm2.LoadState.LuaCompiler;
|
||||
@@ -52,14 +53,25 @@ public class JavaBytecodeCompiler implements LuaCompiler {
|
||||
LoadState.compiler = getInstance();
|
||||
}
|
||||
|
||||
private JavaBytecodeCompiler() {
|
||||
public JavaBytecodeCompiler() {
|
||||
luac = new LuaC();
|
||||
gen = new JavaBytecodeGenerator();
|
||||
}
|
||||
|
||||
/** Compile int a prototype */
|
||||
public static Prototype compile(InputStream is, String chunkname) throws IOException {
|
||||
return getInstance().compile(is.read(), is, chunkname);
|
||||
}
|
||||
|
||||
/** Compile and load a chunk
|
||||
* @throws IOException */
|
||||
public static LuaValue load(InputStream is, String filename, LuaValue _g) throws IOException {
|
||||
return getInstance().load(is.read(), is, filename, _g);
|
||||
}
|
||||
|
||||
/** Compile into protoype form. */
|
||||
public Prototype compile(int firstByte, InputStream stream, String name) throws IOException {
|
||||
return luac.compile(firstByte, stream, name);
|
||||
public Prototype compile(int firstByte, InputStream stream, String chunkname) throws IOException {
|
||||
return luac.compile(firstByte, stream, chunkname);
|
||||
}
|
||||
|
||||
/** Compile into class form. */
|
||||
@@ -70,10 +82,8 @@ public class JavaBytecodeCompiler implements LuaCompiler {
|
||||
classname = classname.replace('/', '.');
|
||||
classname = classname.replace('\\', '.');
|
||||
String sourcename = filename.substring( filename.lastIndexOf('/')+1 );
|
||||
System.out.println("compiling file "+filename+" using sourcename "+sourcename+" and classname "+classname);
|
||||
Class c = gen.toJavaBytecode(p, classname, sourcename);
|
||||
Object o = c.newInstance();
|
||||
System.out.println("instance is: "+o);
|
||||
LuaFunction f = (LuaFunction) o;
|
||||
f.setfenv(env);
|
||||
return f;
|
||||
|
||||
@@ -284,6 +284,7 @@ public class JavaBytecodeGenerator {
|
||||
int np = p.numparams;
|
||||
int nl = p.maxstacksize;
|
||||
LocalVariableGen[] locals = new LocalVariableGen[nl];
|
||||
|
||||
|
||||
|
||||
// initialize locals
|
||||
@@ -292,16 +293,15 @@ public class JavaBytecodeGenerator {
|
||||
// LocalVariableGen regup[] = new LocalVariableGen[nl];
|
||||
boolean isup[] = new boolean[nl];
|
||||
markups(p, isup, code, 0, 0);
|
||||
|
||||
|
||||
// initialize slotc
|
||||
boolean needsarg = ((p.is_vararg & Lua.VARARG_NEEDSARG) != 0);
|
||||
for (int j = 0; j < nl; j++) {
|
||||
|
||||
String name = j < p.locvars.length && p.locvars[j].varname != null ?
|
||||
toLegalJavaName(p.locvars[j].varname.toString()):
|
||||
"r" + j;
|
||||
|
||||
locals[j] = mg.addLocalVariable(name, isup[j] ? TYPE_LOCALUPVALUE
|
||||
: TYPE_LUAVALUE, null, null);
|
||||
|
||||
// create space
|
||||
LuaString luaname = p.getlocalname(j,0);
|
||||
String name = toLegalJavaName( luaname!=null? luaname.toString(): "r"+j );
|
||||
locals[j] = mg.addLocalVariable(name, isup[j] ? TYPE_LOCALUPVALUE : TYPE_LUAVALUE, null, null);
|
||||
|
||||
if (isup[j]) { // upvalue storage
|
||||
il.append(new PUSH(cp, 1));
|
||||
il.append(new ANEWARRAY(cp.addClass(STR_LUAVALUE)));
|
||||
@@ -314,9 +314,11 @@ public class JavaBytecodeGenerator {
|
||||
if (j < np) {
|
||||
il.append(new ALOAD(1));
|
||||
il.append(new PUSH(cp, j + 1));
|
||||
il.append(factory.createInvoke(STR_VARARGS, "arg",
|
||||
TYPE_LUAVALUE, new Type[] { Type.INT },
|
||||
Constants.INVOKEVIRTUAL));
|
||||
il.append(factory.createInvoke(STR_VARARGS, "arg", TYPE_LUAVALUE, new Type[] { Type.INT }, Constants.INVOKEVIRTUAL));
|
||||
} else if ( (j == np) && needsarg ) {
|
||||
il.append(new ALOAD(1));
|
||||
il.append(new PUSH(cp, np+1));
|
||||
il.append(factory.createInvoke(STR_LUAVALUE, "tableOf", TYPE_LUATABLE, new Type[] { TYPE_VARARGS, Type.INT }, Constants.INVOKESTATIC));
|
||||
} else {
|
||||
nil = il_initLocalNil(mg, factory, il, nil);
|
||||
il.append(new ALOAD(nil.getIndex()));
|
||||
@@ -384,6 +386,7 @@ public class JavaBytecodeGenerator {
|
||||
// pc++; /* skip next instruction (if C) */
|
||||
branches[pc] = new GOTO(null);
|
||||
targets[pc] = pc + 2;
|
||||
il.append(branches[pc]);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -475,6 +478,7 @@ public class JavaBytecodeGenerator {
|
||||
// stack[a+1] = (o = stack[B(i)]);
|
||||
ih[pc] =
|
||||
il_append_new_ALOAD(cp,il, (locals[B(i)]));
|
||||
il.append(InstructionConstants.DUP);
|
||||
il_append_new_ASTORE(cp,il, (locals[a+1]));
|
||||
// stack[a] = o.get((c=C(i))>0xff? k[c&0x0ff]: stack[c]);
|
||||
if ((c=C(i))>0xff)
|
||||
@@ -880,12 +884,14 @@ public class JavaBytecodeGenerator {
|
||||
//o = stack[a];
|
||||
il_append_new_ALOAD(cp,il, (locals[a]));
|
||||
if ( (b=B(i)) == 0 ) {
|
||||
for ( int j=1; a+j<vbase; j++ ) {
|
||||
int j=1;
|
||||
for ( ; a+j<vbase; j++ ) {
|
||||
il.append(InstructionConstants.DUP);
|
||||
il.append(new PUSH(cp,offset+j));
|
||||
il_append_new_ALOAD(cp,il, (locals[a+j]));
|
||||
il.append(factory.createInvoke(STR_LUAVALUE, "rawset", Type.VOID, new Type[] { Type.INT, TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL));
|
||||
}
|
||||
il.append(new PUSH(cp,offset+j));
|
||||
il.append(new ALOAD(v.getIndex()));
|
||||
il.append(factory.createInvoke(STR_LUAVALUE, "rawsetlist", Type.VOID, new Type[] { Type.INT, TYPE_VARARGS }, Constants.INVOKEVIRTUAL));
|
||||
} else {
|
||||
|
||||
@@ -26,7 +26,8 @@ import java.io.InputStream;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.luaj.vm2.luajc.LuaJCompiler;
|
||||
import org.luaj.vm2.compiler.LuaC;
|
||||
import org.luaj.vm2.luajc.JavaBytecodeCompiler;
|
||||
|
||||
/**
|
||||
* Test compilation of various fragments that have
|
||||
@@ -40,9 +41,12 @@ public class FragmentsTest extends TestCase {
|
||||
String name = getName();
|
||||
LuaTable _G = org.luaj.vm2.lib.JsePlatform.standardGlobals();
|
||||
InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8"));
|
||||
String java = LuaJCompiler.compileToJava(is, name);
|
||||
LuaValue chunk = LuaJCompiler.javaCompile(java, name);
|
||||
chunk.setfenv(_G);
|
||||
LuaValue chunk ;
|
||||
if ( true ) {
|
||||
chunk = JavaBytecodeCompiler.load(is,name,_G);
|
||||
} else {
|
||||
chunk = (new LuaC()).load( is, name, _G );
|
||||
}
|
||||
Varargs actual = chunk.invoke();
|
||||
assertEquals( expected.narg(), actual.narg() );
|
||||
for ( int i=1; i<=actual.narg(); i++ )
|
||||
@@ -54,14 +58,69 @@ public class FragmentsTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testArgParam() {
|
||||
// the name "arg" is treated specially, and ends up masking the argument value in 5.1
|
||||
runFragment( LuaValue.NIL,
|
||||
public void testVarVarargsUseArg() {
|
||||
runFragment( LuaValue.varargsOf( new LuaValue[] {
|
||||
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 void testVarVarargsUseBoth() {
|
||||
runFragment( LuaValue.varargsOf( new LuaValue[] {
|
||||
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" +
|
||||
" return arg,...\n" +
|
||||
"end\n" +
|
||||
"return v('a','b','c')\n" );
|
||||
}
|
||||
|
||||
public void testArgParamUseNone() {
|
||||
// the name "arg" is treated specially, and ends up masking the argument value in 5.1
|
||||
runFragment( LuaValue.valueOf("table"),
|
||||
"function v(arg,...)\n" +
|
||||
" return type(arg)\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() {
|
||||
@@ -192,7 +251,7 @@ public class FragmentsTest extends TestCase {
|
||||
public void testNoReturnValuesPlainCall() {
|
||||
runFragment( LuaValue.TRUE,
|
||||
"local testtable = {}\n"+
|
||||
"return pcall( function() testtable[1]=2 end ) )\n" );
|
||||
"return pcall( function() testtable[1]=2 end )\n" );
|
||||
}
|
||||
|
||||
public void testVarargsInTableConstructor() {
|
||||
|
||||
Reference in New Issue
Block a user