Mercurial Hosting > luan
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;