Package org.luaj.vm2.lua2java

Source Code of org.luaj.vm2.lua2java.Lua2Java

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
        StandardJavaFileManager fm = compiler.getStandardFileManager( null, null, null);
        fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File[] { new File(binDirRoot) }));
       
        // compile the file
        CompilationTask task = compiler.getTask(null, fm, null, null, null, fm.getJavaFileObjects(source));
        boolean success = task.call().booleanValue();

        // 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;
    }
  } 
}
TOP

Related Classes of org.luaj.vm2.lua2java.Lua2Java

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.