Mercurial Hosting > luan
changeset 652:067d9470184d
compile SetStmt and ForStmt
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Mon, 04 Apr 2016 23:26:06 -0600 |
parents | 140cc5191b7a |
children | 538b0ae08faa |
files | core/src/luan/impl/$Luan.java core/src/luan/impl/BreakException.java core/src/luan/impl/LuanJavaCompiler.java core/src/luan/impl/LuanParser.java core/src/luan/impl/LuanStateImpl.java core/src/luan/impl/Settable.java |
diffstat | 6 files changed, 165 insertions(+), 34 deletions(-) [+] |
line wrap: on
line diff
--- a/core/src/luan/impl/$Luan.java Fri Apr 01 17:24:44 2016 -0600 +++ b/core/src/luan/impl/$Luan.java Mon Apr 04 23:26:06 2016 -0600 @@ -40,6 +40,19 @@ } + private static List<Settable> listSettable = new ArrayList<Settable>(); + + static int addSettable(Settable settable) { + int i = listSettable.size(); + listSettable.add(settable); + return i; + } + + public static Settable getSettable(int i) { + return listSettable.get(i); + } + + public static Object first(Object obj) { return Luan.first(obj); } @@ -76,6 +89,10 @@ return Luan.checkBoolean(o); } + public static LuanFunction checkFunction(Object o) throws LuanException { + return Luan.checkFunction(o); + } + public static boolean not(Object o) throws LuanException { return !checkBoolean(o); } @@ -194,4 +211,20 @@ public static void nop(Object o) {} + + public static void set(LuanStateImpl luan,Settable[] vars,Object obj) throws LuanException { + if( obj instanceof Object[] ) { + Object[] vals = (Object[])obj; + for( int i=0; i<vars.length; i++ ) { + Object val = i < vals.length ? vals[i] : null; + vars[i].set(luan,val); + } + } else { + vars[0].set(luan,obj); + for( int i=1; i<vars.length; i++ ) { + vars[i].set(luan,null); + } + } + } + }
--- a/core/src/luan/impl/BreakException.java Fri Apr 01 17:24:44 2016 -0600 +++ b/core/src/luan/impl/BreakException.java Mon Apr 04 23:26:06 2016 -0600 @@ -1,4 +1,4 @@ package luan.impl; -final class BreakException extends RuntimeException {} +public final class BreakException extends RuntimeException {}
--- a/core/src/luan/impl/LuanJavaCompiler.java Fri Apr 01 17:24:44 2016 -0600 +++ b/core/src/luan/impl/LuanJavaCompiler.java Mon Apr 04 23:26:06 2016 -0600 @@ -51,7 +51,7 @@ StringWriter out = new StringWriter(); boolean b = compiler.getTask(out, fjfm, null, null, null, Collections.singletonList(sourceFile)).call(); if( !b ) - throw new RuntimeException("\n"+out); + throw new RuntimeException("\n"+out+"\ncode:\n"+code+"\n"); byte[] byteCode = baos.toByteArray(); int max = byteCode.length-len-3; outer:
--- a/core/src/luan/impl/LuanParser.java Fri Apr 01 17:24:44 2016 -0600 +++ b/core/src/luan/impl/LuanParser.java Mon Apr 04 23:26:06 2016 -0600 @@ -249,13 +249,13 @@ if( (stmt=stmtStr(ReturnStmt())) != null || (stmt=stmtStr(FunctionStmt())) != null || (stmt=stmtStr(LocalFunctionStmt())) != null - || (stmt=stmtStr(BreakStmt())) != null - || (stmt=stmtStr(ForStmt())) != null + || (stmt=BreakStmt()) != null + || (stmt=ForStmt()) != null || (stmt=DoStmt()) != null || (stmt=WhileStmt()) != null || (stmt=RepeatStmt()) != null || (stmt=stmtStr(IfStmt())) != null - || (stmt=stmtStr(SetStmt())) != null + || (stmt=SetStmt()) != null || (stmt=ExpressionsStmt()) != null ) { stmts.append(stmt.code); @@ -345,16 +345,19 @@ return parser.success( new SetStmt( new SetLocalVar(symbolsSize()-1), fnDef ) ); } - private Stmt BreakStmt() throws ParseException { + private StmtString BreakStmt() throws ParseException { parser.begin(); if( !Keyword("break",In.NOTHING) ) return parser.failure(null); if( frame.loops <= 0 ) throw parser.exception("'break' outside of loop"); - return parser.success( new BreakStmt() ); +// return parser.success( new StmtString("break;\n") ); + return parser.success( new StmtString(new BreakStmt()) ); } - private Stmt ForStmt() throws ParseException { + int forCounter = 0; + + private StmtString ForStmt() throws ParseException { parser.begin(); int stackStart = symbolsSize(); if( !Keyword("for",In.NOTHING) ) @@ -362,12 +365,37 @@ List<String> names = RequiredNameList(In.NOTHING); if( !Keyword("in",In.NOTHING) ) return parser.failure(null); - Expr expr = expr(exp(RequiredExpr(In.NOTHING))); + ExpString expr = RequiredExpr(In.NOTHING).expr(); RequiredKeyword("do",In.NOTHING); + + SetLocalVar[] vars = new SetLocalVar[names.size()]; + for( int i=0; i<vars.length; i++ ) { + vars[i] = new SetLocalVar(stackStart+i); + } + String varsStr = varsToString(vars); + + ExpString firstVar = new ExpString(new GetLocalVar(stackStart)); addSymbols(names); - Stmt loop = stmt(RequiredLoopBlock()); + StmtString loop = RequiredLoopBlock(); RequiredKeyword("end",In.NOTHING); - Stmt stmt = new ForStmt( stackStart, symbolsSize() - stackStart, expr, loop ); + String fnVar = "$fn"+ ++forCounter; + String code = "" + +"try {\n" + +"LuanFunction "+fnVar+" = $Luan.checkFunction(" + expr.code + ");\n" + +"while(true) {\n" + +"for( int i="+stackStart+"; i<"+symbolsSize()+"; i++ ) {\n" + +"$luan.stackSet(i,null);\n" + +"}\n" + +"$Luan.set($luan," + varsStr + ", "+fnVar+".call($luan) );\n" + +"if( " + firstVar.code + "==null ) break;\n" + + loop.code + +"}" + +"} catch(BreakException e) {\n" + +"} finally {\n" + +"$luan.stackClear("+stackStart+","+symbolsSize()+");\n" + +"}\n" + ; + StmtString stmt = new StmtString(code); popSymbols( symbolsSize() - stackStart ); return parser.success(stmt); } @@ -393,7 +421,7 @@ } if( parser.match( '=' ) ) { Spaces(In.NOTHING); - Expressions values = ExpList(In.NOTHING); + ExpString values = ExpStringList(In.NOTHING); if( values==null ) throw parser.exception("Expressions expected"); SetLocalVar[] vars = new SetLocalVar[names.size()]; @@ -401,7 +429,9 @@ for( int i=0; i<vars.length; i++ ) { vars[i] = new SetLocalVar(stackStart+i); } - stmts.append( new StmtString(new SetStmt( vars, values )).code ); + String varsStr = varsToString(vars); + String code = "$Luan.set($luan," + varsStr + "," + values.code + ");\n"; + stmts.append(code); } addSymbols(names); return parser.success(); @@ -502,7 +532,7 @@ return new IfStmt(cnd,thenBlock,elseBlock); } - private Stmt SetStmt() throws ParseException { + private StmtString SetStmt() throws ParseException { parser.begin(); List<Settable> vars = new ArrayList<Settable>(); Settable s = SettableVar(); @@ -519,11 +549,24 @@ if( !parser.match( '=' ) ) return parser.failure(null); Spaces(In.NOTHING); - Expressions values = ExpList(In.NOTHING); + ExpString values = ExpStringList(In.NOTHING); if( values==null ) // throw parser.exception("Expressions expected"); return parser.failure(null); - return parser.success( new SetStmt( vars.toArray(new Settable[0]), values ) ); + String varsStr = varsToString(vars.toArray(new Settable[0])); + String code = "$Luan.set($luan," + varsStr + "," + values.code + "); "; + return parser.success( new StmtString(code) ); +//qqq + } + + private static String varsToString(Settable[] vars) { + StringBuilder sb = new StringBuilder(); + sb.append( "new Settable[]{" ); + for( Settable v : vars ) { + sb.append( new SettableString(v).code ).append( ',' ); + } + sb.append( "}" ); + return sb.toString(); } private StmtString ExpressionsStmt() throws ParseException { @@ -908,7 +951,7 @@ return parser.success(indexVar(expr(exp1),exp2)); return parser.failure(null); } - FnCall fnCall = Args( in, expr(exp1), new ArrayList<Expressions>() ); + FnCall fnCall = Args( in, expr(exp1), new ArrayList<ExpString>() ); if( fnCall != null ) return parser.success(exprVar(fnCall)); return parser.failure(null); @@ -988,14 +1031,14 @@ }; } - private FnCall Args(In in,Expr fn,List<Expressions> builder) throws ParseException { + private FnCall Args(In in,Expr fn,List<ExpString> builder) throws ParseException { parser.begin(); return args(in,builder) - ? parser.success( new FnCall( fn, ExpList.build(builder) ) ) + ? parser.success( new FnCall( fn, ExpList.build(expList(builder)) ) ) : parser.failure((FnCall)null); } - private boolean args(In in,List<Expressions> builder) throws ParseException { + private boolean args(In in,List<ExpString> builder) throws ParseException { parser.begin(); if( parser.match('(') ) { In inParens = in.parens(); @@ -1008,12 +1051,12 @@ } Expr exp = TableExpr(in); if( exp != null ) { - builder.add(exp); + builder.add(new ExpString(exp)); return parser.success(); } String s = StringLiteral(in); if( s != null ) { - builder.add( new ConstExpr(s) ); + builder.add( new ExpString(new ConstExpr(s)) ); return parser.success(); } /* @@ -1027,29 +1070,34 @@ } private Expressions ExpList(In in) throws ParseException { - List<Expressions> builder = new ArrayList<Expressions>(); - return ExpList(in,builder) ? ExpList.build(builder) : null; + List<ExpString> builder = new ArrayList<ExpString>(); + return ExpList(in,builder) ? ExpList.build(expList(builder)) : null; } - private boolean ExpList(In in,List<Expressions> builder) throws ParseException { + private ExpString ExpStringList(In in) throws ParseException { + List<ExpString> builder = new ArrayList<ExpString>(); + return ExpList(in,builder) ? exp(builder) : null; + } + + private boolean ExpList(In in,List<ExpString> builder) throws ParseException { parser.begin(); Expressions exp = TemplateExpressions(in); if( exp != null ) { - builder.add(exp); + builder.add(new ExpString(exp)); return parser.success(); } - exp = exp(ExprZ(in)); - if( exp==null ) + ExpString es = ExprZ(in); + if( es==null ) return parser.failure(); - builder.add(exp); + builder.add(es); while( parser.match(',') ) { Spaces(in); exp = TemplateExpressions(in); if( exp != null ) { - builder.add(exp); + builder.add(new ExpString(exp)); return parser.success(); } - builder.add( exp(RequiredExpr(in)) ); + builder.add( RequiredExpr(in) ); } return parser.success(); } @@ -1469,6 +1517,38 @@ return expStr==null ? null : expStr.toExpressions(); } + private ExpString exp(List<ExpString> list) { + switch(list.size()) { + case 0: + return new ExpString("null",true,false); + case 1: + return list.get(0).expr(); + default: + int lastI = list.size() - 1; + StringBuilder sb = new StringBuilder(); + sb.append( "new Object[]{" ); + for( int i=0; i<lastI; i++ ) { + sb.append( list.get(i).expr().code ).append( ',' ); + } + ExpString last = list.get(lastI); + if( last.isExpr ) { + sb.append( last.code ).append( '}' ); + return new ExpString(sb.toString(),false,false); + } else { + sb.append( '}' ); + String s = "$Luan.concatArgs(" + sb + "," + last.code + ")"; + return new ExpString(s,false,false); + } + } + } + + private static List<Expressions> expList(List<ExpString> esList) { + List<Expressions> list = new ArrayList<Expressions>(); + for( ExpString es : esList ) { + list.add(exp(es)); + } + return list; + } private static class StmtString { final String code; @@ -1481,12 +1561,14 @@ StmtString(String code) { this.code = code; + if( code.contains("LuanParser") ) throw new RuntimeException("\n"+code); } Stmt toStmt() { String className = "EXP" + ++classCounter; String classCode = "" +"package luan.impl;\n" + +"import luan.LuanFunction;\n" +"import luan.LuanException;\n" +"\n" +"public class " + className +" implements Stmt {\n" @@ -1498,7 +1580,7 @@ ; //System.out.println(code); try { - Class cls = LuanJavaCompiler.compile("luan.impl."+className,code,classCode); + Class cls = LuanJavaCompiler.compile("luan.impl."+className,"code",classCode); return (Stmt)cls.newInstance(); } catch(ClassNotFoundException e) { throw new RuntimeException(e); @@ -1520,4 +1602,20 @@ return stmt==null ? null : new StmtString(stmt); } + + private static class SettableString { + final String code; + + SettableString(Settable settable) { + if( settable==null ) throw new NullPointerException(); + int i = $Luan.addSettable(settable); + code = "$Luan.getSettable(" + i + ")"; + } + + SettableString(String code) { + this.code = code; + } + + } + }
--- a/core/src/luan/impl/LuanStateImpl.java Fri Apr 01 17:24:44 2016 -0600 +++ b/core/src/luan/impl/LuanStateImpl.java Mon Apr 04 23:26:06 2016 -0600 @@ -86,7 +86,7 @@ return frame.stack[index]; } - void stackSet(int index,Object value) { + public void stackSet(int index,Object value) { frame.stack[index] = value; }
--- a/core/src/luan/impl/Settable.java Fri Apr 01 17:24:44 2016 -0600 +++ b/core/src/luan/impl/Settable.java Mon Apr 04 23:26:06 2016 -0600 @@ -3,6 +3,6 @@ import luan.LuanException; -interface Settable { +public interface Settable { public void set(LuanStateImpl luan,Object value) throws LuanException; }