Expand compiler interface, add bcel-based bytecode generator.

This commit is contained in:
James Roseborough
2009-10-29 22:20:56 +00:00
parent 0b6cd02bc6
commit f729c1b626
13 changed files with 1224 additions and 41 deletions

View File

@@ -15,5 +15,6 @@
<classpathentry kind="var" path="ANTLR_HOME"/> <classpathentry kind="var" path="ANTLR_HOME"/>
<classpathentry kind="var" path="WTK_HOME/lib/cldcapi11.jar"/> <classpathentry kind="var" path="WTK_HOME/lib/cldcapi11.jar"/>
<classpathentry kind="var" path="WTK_HOME/lib/midpapi20.jar"/> <classpathentry kind="var" path="WTK_HOME/lib/midpapi20.jar"/>
<classpathentry kind="var" path="BCEL_LIB"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

View File

@@ -39,8 +39,7 @@ public class LoadState {
/** format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints */ /** format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints */
public static final int NUMBER_FORMAT_NUM_PATCH_INT32 = 4; public static final int NUMBER_FORMAT_NUM_PATCH_INT32 = 4;
// type constants // type constants
public static final int LUA_TINT = (-2); public static final int LUA_TINT = (-2);
public static final int LUA_TNONE = (-1); public static final int LUA_TNONE = (-1);
public static final int LUA_TNIL = 0; public static final int LUA_TNIL = 0;
@@ -56,7 +55,10 @@ public class LoadState {
/** Interface for the compiler, if it is installed. */ /** Interface for the compiler, if it is installed. */
public interface LuaCompiler { public interface LuaCompiler {
/** Compile into a prototype, without taking the additional step of create a LuaFunction or LuaClosure */
public Prototype compile(int firstByte, InputStream stream, String name) throws IOException; public Prototype compile(int firstByte, InputStream stream, String name) throws IOException;
/** Load into a Closure or LuaFunction, with the supplied initial environment */
public LuaFunction load(int firstByte, InputStream stream, String name, LuaValue env) throws IOException;
} }
/** Compiler instance, if installed */ /** Compiler instance, if installed */
@@ -266,12 +268,11 @@ public class LoadState {
luacNumberFormat = is.readByte(); luacNumberFormat = is.readByte();
} }
public static Prototype undump( InputStream stream, String name ) throws IOException { public static LuaFunction load( InputStream stream, String name, LuaValue env ) throws IOException {
// check first byte to see if its a precompiled chunk
int c = stream.read(); int c = stream.read();
if ( c != LUA_SIGNATURE[0] ) { if ( c != LUA_SIGNATURE[0] ) {
if ( compiler != null ) if ( compiler != null )
return compiler.compile(c, stream, name); return compiler.load(c, stream, name, env);
throw new LuaError("no compiler"); throw new LuaError("no compiler");
} }
@@ -296,7 +297,8 @@ public class LoadState {
throw new LuaError("unsupported int size"); throw new LuaError("unsupported int size");
} }
return s.loadFunction( LuaString.valueOf(sname) ); Prototype p = s.loadFunction( LuaString.valueOf(sname) );
return new LuaClosure( p, env );
} }
public static String getSourceName(String name) { public static String getSourceName(String name) {

View File

@@ -310,6 +310,7 @@ public class LuaValue extends Varargs {
// table initializers // table initializers
public static LuaTable tableOf() { return new LuaTable(); } public static LuaTable tableOf() { return new LuaTable(); }
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) { return new LuaTable(null,unnamedValues,null); }
public static LuaTable listOf(LuaValue[] unnamedValues,Varargs lastarg) { return new LuaTable(null,unnamedValues,lastarg); } public static LuaTable listOf(LuaValue[] unnamedValues,Varargs lastarg) { return new LuaTable(null,unnamedValues,lastarg); }
public static LuaTable tableOf(LuaValue[] namedValues) { return new LuaTable(namedValues,null,null); } public static LuaTable tableOf(LuaValue[] namedValues) { return new LuaTable(namedValues,null,null); }

View File

@@ -299,7 +299,11 @@ public class Print extends Lua {
} }
} }
public void printFunction(Prototype f, boolean full) { public static void print(Prototype p) {
printFunction(p, true);
}
public static void printFunction(Prototype f, boolean full) {
int i, n = f.p.length; int i, n = f.p.length;
printHeader(f); printHeader(f);
printCode(f); printCode(f);

View File

@@ -27,10 +27,12 @@ import java.util.Hashtable;
import org.luaj.vm2.LocVars; import org.luaj.vm2.LocVars;
import org.luaj.vm2.Lua; import org.luaj.vm2.Lua;
import org.luaj.vm2.LuaClosure;
import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaError;
import org.luaj.vm2.Prototype; import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaString; import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaValue; import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.LoadState.LuaCompiler; import org.luaj.vm2.LoadState.LuaCompiler;
@@ -158,8 +160,19 @@ public class LuaC extends Lua implements LuaCompiler {
/** Utility method to invoke the compiler for an input stream /** Utility method to invoke the compiler for an input stream
*/ */
public static Prototype compile(InputStream is, String string) throws IOException { public static Prototype compile(InputStream is, String name) throws IOException {
return new LuaC().compile(is.read(), is, string); return new LuaC().compile(is.read(), is, name);
}
/** Load into a Closure or LuaFunction, with the supplied initial environment */
public static LuaFunction load(InputStream is, String name, LuaValue env) throws IOException {
return new LuaC().load(is.read(), is, name, env);
}
/** Load into a Closure or LuaFunction, with the supplied initial environment */
public LuaFunction load(int firstByte, InputStream stream, String name, LuaValue env) throws IOException {
Prototype p = compile(firstByte, stream, name);
return new LuaClosure( p, env );
} }
/** Compile source bytes into a LPrototype. /** Compile source bytes into a LPrototype.

View File

@@ -222,8 +222,7 @@ public class BaseLib extends LuaTable implements ResourceFinder {
try { try {
LuaValue func = args.checkfunction(1); LuaValue func = args.checkfunction(1);
String chunkname = args.optString(2, "function"); String chunkname = args.optString(2, "function");
Prototype p = LoadState.undump(new StringInputStream(func), chunkname); return LoadState.load(new StringInputStream(func), chunkname, LuaThread.getRunningEnv(env));
return new LuaClosure(p,LuaThread.getRunningEnv(env));
} catch ( Exception e ) { } catch ( Exception e ) {
return varargsOf(NIL, valueOf(e.getMessage())); return varargsOf(NIL, valueOf(e.getMessage()));
} }
@@ -240,8 +239,7 @@ public class BaseLib extends LuaTable implements ResourceFinder {
try { try {
LuaString script = args.checkstring(1); LuaString script = args.checkstring(1);
LuaString chunkname = args.optstring(2, script); LuaString chunkname = args.optstring(2, script);
Prototype p = LoadState.undump(script.toInputStream(), chunkname.toString()); return LoadState.load(script.toInputStream(), chunkname.toString(),LuaThread.getRunningEnv(env));
return new LuaClosure(p,LuaThread.getRunningEnv(env));
} catch ( Exception e ) { } catch ( Exception e ) {
return varargsOf(NIL, valueOf(e.getMessage())); return varargsOf(NIL, valueOf(e.getMessage()));
} }
@@ -344,8 +342,7 @@ public class BaseLib extends LuaTable implements ResourceFinder {
if ( is == null ) if ( is == null )
return varargsOf(NIL, valueOf("not found: "+filename)); return varargsOf(NIL, valueOf("not found: "+filename));
try { try {
Prototype p = LoadState.undump(is, filename); return LoadState.load(is, filename, LuaThread.getRunningEnv(env));
return new LuaClosure(p,LuaThread.getRunningEnv(env));
} finally { } finally {
is.close(); is.close();
} }

View File

@@ -29,9 +29,8 @@ import java.io.InputStreamReader;
import org.luaj.vm2.LoadState; import org.luaj.vm2.LoadState;
import org.luaj.vm2.Lua; import org.luaj.vm2.Lua;
import org.luaj.vm2.LuaClosure; import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaValue; import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.compiler.LuaC; import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.DebugLib; import org.luaj.vm2.lib.DebugLib;
import org.luaj.vm2.lib.JsePlatform; import org.luaj.vm2.lib.JsePlatform;
@@ -167,10 +166,9 @@ public class lua {
private static void processScript( InputStream script, String chunkname, String[] args, int offset ) throws IOException { private static void processScript( InputStream script, String chunkname, String[] args, int offset ) throws IOException {
try { try {
LuaClosure c; LuaFunction c;
try { try {
Prototype p = LoadState.undump(script, chunkname ); c = LoadState.load(script, chunkname, _G);
c = new LuaClosure(p,_G);
} finally { } finally {
script.close(); script.close();
} }

View File

@@ -0,0 +1,83 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.luajc;
import java.io.IOException;
import java.io.InputStream;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaClosure;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.LoadState.LuaCompiler;
import org.luaj.vm2.compiler.LuaC;
public class JavaBytecodeCompiler implements LuaCompiler {
private static JavaBytecodeCompiler instance;
private JavaBytecodeGenerator gen;
private LuaC luac;
public static JavaBytecodeCompiler getInstance() {
if ( instance == null )
instance = new JavaBytecodeCompiler();
return instance;
}
/**
* Install the compiler as the main compiler to use.
* Will fall back to the LuaC prototype compiler.
*/
public static final void install() {
LoadState.compiler = getInstance();
}
private JavaBytecodeCompiler() {
luac = new LuaC();
gen = new JavaBytecodeGenerator();
}
/** Compile into protoype form. */
public Prototype compile(int firstByte, InputStream stream, String name) throws IOException {
return luac.compile(firstByte, stream, name);
}
/** Compile into class form. */
public LuaFunction load(int firstByte, InputStream stream, String name, LuaValue env) throws IOException {
Prototype p = compile( firstByte, stream, name);
try {
System.out.println("compiling "+name);
Class c = gen.toJavaBytecode(p, name);
Object o = c.newInstance();
System.out.println("instance is: "+o);
LuaFunction f = (LuaFunction) o;
f.setfenv(env);
return f;
} catch ( Throwable t ) {
t.printStackTrace();
return new LuaClosure( p, env );
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -43,6 +43,7 @@ import org.luaj.vm2.LoadState;
import org.luaj.vm2.Lua; import org.luaj.vm2.Lua;
import org.luaj.vm2.LuaClosure; import org.luaj.vm2.LuaClosure;
import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaValue; import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype; import org.luaj.vm2.Prototype;
import org.luaj.vm2.compiler.LuaC; import org.luaj.vm2.compiler.LuaC;
@@ -165,18 +166,41 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
try { try {
InputStream ris = new Utf8Encoder(reader); InputStream ris = new Utf8Encoder(reader);
try { try {
final Prototype p = LoadState.undump(ris, "script"); final LuaFunction f = LoadState.load(ris, "script", null);
return new CompiledScript() { if ( f.isclosure() ) {
public Object eval(ScriptContext context) throws ScriptException { LuaClosure c = f.checkclosure();
Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE); final Prototype p = c.p;
LuaBindings lb = (LuaBindings) b; return new CompiledScript() {
LuaClosure c = new LuaClosure( p, lb.env ); public Object eval(ScriptContext context) throws ScriptException {
return c.call(); Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE);
} LuaBindings lb = (LuaBindings) b;
public ScriptEngine getEngine() { LuaClosure c = new LuaClosure( p, lb.env );
return LuaScriptEngine.this; return c.invoke(LuaValue.NONE);
} }
}; public ScriptEngine getEngine() {
return LuaScriptEngine.this;
}
};
} else {
final Class c = f.getClass();
return new CompiledScript() {
public Object eval(ScriptContext context) throws ScriptException {
Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE);
LuaBindings lb = (LuaBindings) b;
LuaFunction lf;
try {
lf = (LuaFunction) c.newInstance();
} catch (Exception e) {
throw new ScriptException("instantiation failed: "+e.toString());
}
lf.setfenv(lb.env);
return lf.invoke(LuaValue.NONE);
}
public ScriptEngine getEngine() {
return LuaScriptEngine.this;
}
};
}
} catch ( LuaError lee ) { } catch ( LuaError lee ) {
throw new ScriptException(lee.getMessage() ); throw new ScriptException(lee.getMessage() );
} finally { } finally {

View File

@@ -57,7 +57,6 @@ public class AllTests {
// luajc regression tests // luajc regression tests
TestSuite luajc = new TestSuite("Luajc Tests"); TestSuite luajc = new TestSuite("Luajc Tests");
luajc.addTestSuite(FragmentsTest.class); luajc.addTestSuite(FragmentsTest.class);
luajc.addTest( new TestSuite( LuaJCCompatibilityTest.class, "LuaJC Compatiblity Tests" ) );
suite.addTest(luajc); suite.addTest(luajc);
return suite; return suite;

View File

@@ -24,6 +24,8 @@ package org.luaj.vm2;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.luaj.vm2.luajc.JavaBytecodeCompiler;
/** /**
* Compatibility tests for the Luaj VM * Compatibility tests for the Luaj VM
* *
@@ -59,6 +61,8 @@ public class CompatibiltyTest {
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( LuaJCCompatibilityTest.class, "LuaJC Gen Tests" ) );
return suite; return suite;
} }
@@ -76,8 +80,18 @@ public class CompatibiltyTest {
super(ScriptDrivenTest.PlatformType.JSE); super(ScriptDrivenTest.PlatformType.JSE);
} }
protected void setUp() throws Exception { protected void setUp() throws Exception {
System.setProperty("JME", "false");
super.setUp(); super.setUp();
System.setProperty("JME", "false");
}
}
public static class JseBytecodeTest extends CompatibiltyTestSuite {
public JseBytecodeTest() {
super(ScriptDrivenTest.PlatformType.JSE);
}
protected void setUp() throws Exception {
super.setUp();
System.setProperty("JME", "false");
JavaBytecodeCompiler.install();
} }
} }
public static class LuaJCCompatibilityTest extends CompatibiltyTestSuite { public static class LuaJCCompatibilityTest extends CompatibiltyTestSuite {
@@ -85,8 +99,8 @@ public class CompatibiltyTest {
super(ScriptDrivenTest.PlatformType.LUAJIT); super(ScriptDrivenTest.PlatformType.LUAJIT);
} }
protected void setUp() throws Exception { protected void setUp() throws Exception {
System.setProperty("JME", "false");
super.setUp(); super.setUp();
System.setProperty("JME", "false");
} }
// skipping - not supported yet // skipping - not supported yet
public void testDebugLib() {} public void testDebugLib() {}

View File

@@ -31,9 +31,7 @@ import java.io.PrintStream;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.BaseLib; import org.luaj.vm2.lib.BaseLib;
import org.luaj.vm2.lib.CoroutineLib;
import org.luaj.vm2.lib.DebugLib; import org.luaj.vm2.lib.DebugLib;
import org.luaj.vm2.luajc.LuaJCompiler; import org.luaj.vm2.luajc.LuaJCompiler;
@@ -58,7 +56,6 @@ public class ScriptDrivenTest extends TestCase {
try { try {
// create globals // create globals
LuaC.install();
LuaTable _G = null; LuaTable _G = null;
switch ( platform ) { switch ( platform ) {
default: default:
@@ -120,8 +117,7 @@ public class ScriptDrivenTest extends TestCase {
} }
default: default:
script = new FileInputStream(file); script = new FileInputStream(file);
Prototype p = LoadState.undump(script, "stdin"); return LoadState.load(script, "stdin", _G);
return new LuaClosure(p,_G);
} }
} catch ( Exception e ) { } catch ( Exception e ) {
e.printStackTrace(); e.printStackTrace();