changeset 665:41f8fdbc3a0a

compile modules
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 07 Apr 2016 17:06:22 -0600
parents 71f8f5075df8
children 2f449ccf54d2
files core/src/luan/impl/LuanJavaCompiler.java core/src/luan/impl/LuanParser.java
diffstat 2 files changed, 77 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/core/src/luan/impl/LuanJavaCompiler.java	Thu Apr 07 15:11:52 2016 -0600
+++ b/core/src/luan/impl/LuanJavaCompiler.java	Thu Apr 07 17:06:22 2016 -0600
@@ -6,6 +6,8 @@
 import java.io.IOException;
 import java.net.URI;
 import java.util.Collections;
+import java.util.Map;
+import java.util.HashMap;
 import javax.tools.FileObject;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
@@ -19,6 +21,38 @@
 public final class LuanJavaCompiler {
 	private LuanJavaCompiler() {}  // never
 
+	private static class MyJavaFileObject extends SimpleJavaFileObject {
+		final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+		MyJavaFileObject() {
+			super(URI.create("whatever"),JavaFileObject.Kind.CLASS);
+		}
+
+		@Override public OutputStream openOutputStream() {
+			return baos;
+		}
+
+		byte[] byteCode(String sourceName) {
+			byte[] byteCode = baos.toByteArray();
+			final int len = sourceName.length();
+			int max = byteCode.length-len-3;
+			outer:
+			for( int i=0; true; i++ ) {
+				if( i > max )
+					throw new RuntimeException("len="+len);
+				if( byteCode[i]==1 && (byteCode[i+1] << 8 | 0xFF & byteCode[i+2]) == len ) {
+					for( int j=i+3; j<i+3+len; j++ ) {
+						if( byteCode[j] != '$' )
+							continue outer;
+					}
+					System.arraycopy(sourceName.getBytes(),0,byteCode,i+3,len);
+					break;
+				}
+			}
+			return byteCode;
+		}
+	}
+
 	public static Class compile(final String className,final String sourceName,final String code) throws ClassNotFoundException {
 		final int len = sourceName.length();
 		StringBuilder sb = new StringBuilder(sourceName);
@@ -35,16 +69,15 @@
 				return true;
 			}
 		};
-		ByteArrayOutputStream baos = new ByteArrayOutputStream();
-		JavaFileObject classFile = new SimpleJavaFileObject(URI.create("whatever"),JavaFileObject.Kind.CLASS) {
-			@Override public OutputStream openOutputStream() {
-				return baos;
-			}
-		};
+		final Map<String,MyJavaFileObject> map = new HashMap<String,MyJavaFileObject>();
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
 		StandardJavaFileManager sjfm = compiler.getStandardFileManager(null,null,null);
 		ForwardingJavaFileManager fjfm = new ForwardingJavaFileManager(sjfm) {
 			@Override public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
+				if( map.containsKey(className) )
+					throw new RuntimeException(className);
+				MyJavaFileObject classFile = new MyJavaFileObject();
+				map.put(className,classFile);
 				return classFile;
 			}
 		};
@@ -52,24 +85,11 @@
 		boolean b = compiler.getTask(out, fjfm, null, null, null, Collections.singletonList(sourceFile)).call();
 		if( !b )
 			throw new RuntimeException("\n"+out+"\ncode:\n"+code+"\n");
-		final byte[] byteCode = baos.toByteArray();
-		int max = byteCode.length-len-3;
-		outer:
-		for( int i=0; true; i++ ) {
-			if( i > max )
-				throw new RuntimeException("len="+len);
-			if( byteCode[i]==1 && (byteCode[i+1] << 8 | 0xFF & byteCode[i+2]) == len ) {
-				for( int j=i+3; j<i+3+len; j++ ) {
-					if( byteCode[j] != '$' )
-						continue outer;
-				}
-				System.arraycopy(sourceName.getBytes(),0,byteCode,i+3,len);
-				break;
-			}
-		}
 		ClassLoader cl = new ClassLoader() {
 			@Override protected Class<?> findClass(String name) throws ClassNotFoundException {
-				if( name.equals(className) ) {
+				MyJavaFileObject jfo = map.get(name);
+				if( jfo != null ) {
+					byte[] byteCode = jfo.byteCode(sourceName);
 					return defineClass(name, byteCode, 0, byteCode.length);
 				}
 				return super.findClass(name);
--- a/core/src/luan/impl/LuanParser.java	Thu Apr 07 15:11:52 2016 -0600
+++ b/core/src/luan/impl/LuanParser.java	Thu Apr 07 17:06:22 2016 -0600
@@ -177,10 +177,15 @@
 	private FnDef newFnDef(int start,StmtString stmt) {
 		if( !stmt.hasReturn )
 			stmt = new StmtString( stmt.code + "return LuanFunction.NOTHING;\n" );
-//		return new FnDef( toExpressions(stmt), frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) );
 		return toFnDef( stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) );
 	}
 
+	private ExpString newFnExpStr(int start,StmtString stmt) {
+		if( !stmt.hasReturn )
+			stmt = new StmtString( stmt.code + "return LuanFunction.NOTHING;\n" );
+		return toFnExpStr( stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) );
+	}
+
 	FnDef Expression() throws ParseException {
 		Spaces(In.NOTHING);
 		int start = parser.begin();
@@ -188,6 +193,7 @@
 		if( expr != null && parser.endOfInput() ) {
 			String code = "return " + expr.code + ";\n";
 			StmtString stmt = new StmtString(code);
+			stmt.hasReturn = true;
 			return parser.success(newFnDef(start,stmt));
 		}
 		return parser.failure(null);
@@ -353,8 +359,8 @@
 			var = indexVar( var.exp(), exp );
 		}
 
-		FnDef fnDef = RequiredFunction(In.NOTHING);
-		return parser.success( var.set(new ExpString(fnDef)) );
+		ExpString fnDef = RequiredFunction(In.NOTHING);
+		return parser.success( var.set(fnDef) );
 	}
 
 	private StmtString LocalFunctionStmt() throws ParseException {
@@ -363,9 +369,9 @@
 			return parser.failure(null);
 		String name = RequiredName(In.NOTHING);
 		addSymbol( name );
-		FnDef fnDef = RequiredFunction(In.NOTHING);
+		ExpString fnDef = RequiredFunction(In.NOTHING);
 		Settable s = new SetLocalVar(symbolsSize()-1);
-		String code = new SettableString(s).code + ".set(luan," + new ExpString(fnDef).code + ");\n";
+		String code = new SettableString(s).code + ".set(luan," + fnDef.code + ");\n";
 		return parser.success( new StmtString(code) );
 	}
 
@@ -828,25 +834,25 @@
 
 	private ExpString SingleExpr(In in) throws ParseException {
 		parser.begin();
-		Expressions exp = FunctionExpr(in);
-		if( exp != null )
-			return parser.success(new ExpString(exp));
-		ExpString es = VarExp(in);
+		ExpString es = FunctionExpr(in);
 		if( es != null )
 			return parser.success(es);
-		exp = VarArgs(in);
+		es = VarExp(in);
+		if( es != null )
+			return parser.success(es);
+		Expressions exp = VarArgs(in);
 		if( exp != null )
 			return parser.success(new ExpString(exp));
 		return parser.failure(null);
 	}
 
-	private Expr FunctionExpr(In in) throws ParseException {
+	private ExpString FunctionExpr(In in) throws ParseException {
 		if( !Keyword("function",in) )
 			return null;
 		return RequiredFunction(in);
 	}
 
-	private FnDef RequiredFunction(In in) throws ParseException {
+	private ExpString RequiredFunction(In in) throws ParseException {
 		int start = parser.begin();
 		RequiredMatch('(');
 		In inParens = in.parens();
@@ -870,7 +876,7 @@
 		Spaces(in);
 		StmtString block = RequiredBlock();
 		RequiredKeyword("end",in);
-		FnDef fnDef = newFnDef(start,block);
+		ExpString fnDef = newFnExpStr(start,block);
 		frame = frame.parent;
 		return parser.success(fnDef);
 	}
@@ -1587,7 +1593,7 @@
 
 	private static StmtString EMPTY_STMT = new StmtString("");
 
-	static FnDef toFnDef(StmtString stmt,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) {
+	private static FnDef toFnDef(StmtString stmt,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) {
 		int i = LuanImpl.addObj(upValueGetters);
 		String className = "EXP" + ++classCounter;
 		String classCode = ""
@@ -1609,6 +1615,7 @@
 			+"}\n"
 		;
 		try {
+//System.out.println(classCode);
 			Class cls = LuanJavaCompiler.compile("luan.impl."+className,"code",classCode);
 			return (FnDef)cls.newInstance();
 		} catch(ClassNotFoundException e) {
@@ -1620,6 +1627,20 @@
 		}
 	}
 
+	private ExpString toFnExpStr(StmtString stmt,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) {
+		int i = LuanImpl.addObj(upValueGetters);
+		String classCode = ""
+			+"\n"
+			+"new FnDef("+stackSize+","+numArgs+","+isVarArg+",(UpValue.Getter[])LuanImpl.getObj("+i+")) {\n"
+			+"	@Override public Object run(LuanStateImpl luan) throws LuanException {\n"
+			+"		Object t;\n"
+			+"		" + stmt.code
+			+"	}\n"
+			+"}.eval(luan)\n"
+		;
+		return new ExpString(classCode,true,false);
+	}
+
 
 	private static class SettableString {
 		final String code;