simplify LuaCompiler interface and add Lua2Java utility class.

This commit is contained in:
James Roseborough
2010-07-25 22:31:43 +00:00
parent 97b4162423
commit 69bbae70a1
14 changed files with 238 additions and 110 deletions

View File

@@ -159,7 +159,7 @@ public class luac {
private void processScript( InputStream script, String chunkname, OutputStream out ) throws IOException {
try {
// create the chunk
Prototype chunk = LuaC.compile(script, chunkname);
Prototype chunk = LuaC.instance.compile(script, chunkname);
// list the chunk
if (list)

View File

@@ -0,0 +1,168 @@
package org.luaj.vm2.lua2java;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Arrays;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.LoadState.LuaCompiler;
import org.luaj.vm2.ast.Chunk;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.parser.LuaParser;
public class Lua2Java implements LuaCompiler {
public static final Lua2Java instance = new Lua2Java();
public static final void install() {
LoadState.compiler = instance;
}
private Lua2Java() {
}
public LuaFunction load(InputStream stream, String filename, LuaValue env) throws IOException {
// get first byte
if ( ! stream.markSupported() )
stream = new BufferedInputStream( stream );
stream.mark( 1 );
int firstByte = stream.read();
stream.reset();
// we can only sompile sources
if ( firstByte != '\033' ) {
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
if (compiler == null)
LuaValue.error("no java compiler");
// break into package and class
if ( filename.endsWith( ".lua") )
filename = filename.substring(0, filename.length()-4);
String s = filename.replace('\\', '/').replace('/','.').replaceAll("[^\\w]", "_");
int p = s.lastIndexOf('.');
final String packageName = p>=0? s.substring(0,p): null;
final String className = toClassname( s.substring(p+1) );
// open output file
final String pkgSubdir = (packageName!=null? packageName.replace('.','/'): "");
final String srcDirRoot = "lua2java/src";
final String binDirRoot = "lua2java/classes";
final String srcDirname = srcDirRoot+"/"+pkgSubdir;
final String binDirname = binDirRoot+"/"+pkgSubdir;
final String srcFilename = srcDirname + "/" + className + ".java";
// make directories
new File(srcDirname).mkdirs();
new File(binDirname).mkdirs();
// generate java source
try {
LuaParser parser = new LuaParser(stream,"ISO8859-1");
Chunk chunk = parser.Chunk();
File source = new File(srcFilename);
Writer writer = new OutputStreamWriter( new FileOutputStream(source) );
new JavaCodeGen(chunk,writer,packageName,className);
writer.close();
// set up output location
Iterable<? extends File> dest = Arrays.asList(new File[] { new File(binDirRoot) });
StandardJavaFileManager fm = compiler.getStandardFileManager( null, null, null);
fm.setLocation(StandardLocation.CLASS_OUTPUT, dest);
// compile the file
Iterable<? extends JavaFileObject> compilationUnits = fm.getJavaFileObjects(source);
CompilationTask task = compiler.getTask(null, fm, null, null, null, compilationUnits);
boolean success = task.call();
// instantiate, config and return
if (success) {
// create instance
ClassLoader cl = new ClassLoader() {
public Class findClass(String classname) throws ClassNotFoundException {
if ( classname.startsWith(className) ) {
File f = new File( binDirname+"/"+classname+".class");
long n = f.length();
byte[] b = new byte[(int) n];
try {
DataInputStream dis = new DataInputStream( new FileInputStream(f) );
dis.readFully(b);
} catch ( Exception e ) {
throw new RuntimeException("failed to read class bytes: "+e );
}
return defineClass(classname, b, 0, b.length);
}
return super.findClass(classname);
}
};
Class clazz = cl.loadClass(className);
Object instance = clazz.newInstance();
LuaFunction value = (LuaFunction) instance;
value.setfenv( env );
return value;
} else {
}
} catch ( Exception e ) {
LuaValue.error("compile task failed: "+e);
}
// report compilation error
LuaValue.error("compile task failed:");
return null;
}
// fall back to plain compiler
return LuaC.instance.load( stream, filename, env);
}
/** Convert lua filename to valid class name */
public static final String toClassname( String filename ) {
int n=filename.length();
int j=n;
if ( filename.endsWith(".lua") )
j -= 4;
for ( int k=0; k<j; k++ ) {
char c = filename.charAt(k);
if ( (!isClassnamePart(c)) || (c=='/') || (c=='\\') ) {
StringBuffer sb = new StringBuffer(j);
for ( int i=0; i<j; i++ ) {
c = filename.charAt(i);
sb.append(
(isClassnamePart(c))? c:
((c=='/') || (c=='\\'))? '.': '_' );
}
return sb.toString();
}
}
return n==j? filename: filename.substring(0,j);
}
private static final boolean isClassnamePart(char c) {
if ( (c>='a'&&c<='z') || (c>='A'&&c<='Z') || (c>='0'&&c<='9') )
return true;
switch ( c ) {
case '.':
case '$':
case '_':
return true;
default:
return false;
}
}
}

View File

@@ -1,13 +1,11 @@
package org.luaj.vm2.luajc;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.compiler.LuaC;
/*******************************************************************************
* Copyright (c) 2010 Luaj.org. All rights reserved.
@@ -40,25 +38,20 @@ public class JavaLoader extends ClassLoader {
this.env = env;
}
public LuaValue load( InputStream is, String classname, String filename ) throws IOException {
Prototype p = LuaC.compile(is, classname);
return load( p, classname, filename );
}
public LuaValue load( Prototype p, String classname, String filename ) {
public LuaFunction load( Prototype p, String classname, String filename ) {
JavaGen jg = new JavaGen( p, classname, filename );
return load( jg );
}
public LuaValue load( JavaGen jg ) {
public LuaFunction load( JavaGen jg ) {
include( jg );
return load( jg.classname );
}
public LuaValue load(String classname) {
public LuaFunction load(String classname) {
try {
Class c = loadClass( classname );
LuaValue v = (LuaValue) c.newInstance();
LuaFunction v = (LuaFunction) c.newInstance();
v.setfenv(env);
return v;
} catch ( Exception e ) {

View File

@@ -37,7 +37,6 @@ public class LuaJC implements LuaCompiler {
private static final String NON_IDENTIFIER = "[^a-zA-Z0-9_$]";
private static LuaJC instance;
private LuaC luac;
public static LuaJC getInstance() {
if ( instance == null )
@@ -54,12 +53,11 @@ public class LuaJC implements LuaCompiler {
}
public LuaJC() {
luac = new LuaC();
}
public Hashtable compileAll(InputStream script, String classname, String filename) throws IOException {
Hashtable h = new Hashtable();
Prototype p = luac.compile(script.read(), script, classname);
Prototype p = LuaC.instance.compile(script, classname);
JavaGen gen = new JavaGen(p, classname, filename);
insert( h, gen );
return h;
@@ -71,25 +69,11 @@ public class LuaJC implements LuaCompiler {
insert(h, gen.inners[i]);
}
public Prototype compile(int firstByte, InputStream stream, String name) throws IOException {
return luac.compile(firstByte, stream, name);
}
public LuaFunction load(int firstByte, InputStream stream, String name, LuaValue env) throws IOException {
return load( compile(firstByte, stream, name), name, env );
}
public LuaFunction load(Prototype p, String filename, LuaValue env) {
String classname = filename.endsWith(".lua")? filename.substring(0,filename.length()-4): filename;
public LuaFunction load(InputStream stream, String name, LuaValue env) throws IOException {
Prototype p = LuaC.instance.compile(stream, name);
String classname = name.endsWith(".lua")? name.substring(0,name.length()-4): name;
classname = classname.replaceAll(NON_IDENTIFIER, "_");
JavaGen gen = new JavaGen(p, classname, filename);
JavaLoader loader = new JavaLoader(env);
loader.include(gen);
return (LuaFunction) loader.load(p, classname, filename);
return loader.load(p, classname, name);
}
public LuaValue load(InputStream stream, String name, LuaValue env) throws IOException {
return load(stream.read(), stream, name, env);
}
}