Mercurial Hosting > luan
changeset 651:140cc5191b7a
start compiling statements
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Fri, 01 Apr 2016 17:24:44 -0600 |
parents | d658eab7bf4c |
children | 067d9470184d |
files | core/src/luan/impl/$Luan.java core/src/luan/impl/LuanParser.java core/src/luan/impl/LuanStateImpl.java core/src/luan/impl/Stmt.java |
diffstat | 4 files changed, 143 insertions(+), 47 deletions(-) [+] |
line wrap: on
line diff
--- a/core/src/luan/impl/$Luan.java Thu Mar 31 22:43:51 2016 -0600 +++ b/core/src/luan/impl/$Luan.java Fri Apr 01 17:24:44 2016 -0600 @@ -27,6 +27,19 @@ } + private static List<Stmt> listStmt = new ArrayList<Stmt>(); + + static int addStmt(Stmt stmt) { + int i = listStmt.size(); + listStmt.add(stmt); + return i; + } + + public static Stmt getStmt(int i) { + return listStmt.get(i); + } + + public static Object first(Object obj) { return Luan.first(obj); } @@ -59,8 +72,12 @@ throw new LuanException("attempt to perform arithmetic on a "+Luan.type(o)+" value"); } + public static boolean checkBoolean(Object o) throws LuanException { + return Luan.checkBoolean(o); + } + public static boolean not(Object o) throws LuanException { - return !Luan.checkBoolean(o); + return !checkBoolean(o); } private static Object arithmetic(LuanState luan,String op,Object o1,Object o2) throws LuanException { @@ -175,4 +192,6 @@ return !(o == null || Boolean.FALSE.equals(o)); } + public static void nop(Object o) {} + }
--- a/core/src/luan/impl/LuanParser.java Thu Mar 31 22:43:51 2016 -0600 +++ b/core/src/luan/impl/LuanParser.java Fri Apr 01 17:24:44 2016 -0600 @@ -193,14 +193,14 @@ Spaces(In.NOTHING); int start = parser.begin(); frame.isVarArg = true; - Stmt stmt = RequiredBlock(); + Stmt stmt = stmt(RequiredBlock()); if( parser.endOfInput() ) return parser.success(newFnDef(start,stmt)); throw parser.exception(); } - private Stmt RequiredBlock() throws ParseException { - List<Stmt> stmts = new ArrayList<Stmt>(); + private StmtString RequiredBlock() throws ParseException { + StringBuilder stmts = new StringBuilder(); int stackStart = symbolsSize(); Stmt(stmts); while( StmtSep(stmts) ) { @@ -209,23 +209,30 @@ } int stackEnd = symbolsSize(); popSymbols( stackEnd - stackStart ); - if( stmts.isEmpty() ) - return Stmt.EMPTY; - if( stmts.size()==1 && stackStart==stackEnd ) - return stmts.get(0); - return new Block( stmts.toArray(new Stmt[0]), stackStart, stackEnd ); + if( stmts.length() == 0 ) + return EMPTY_STMT; + String code = stmts.toString(); + if( stackStart < stackEnd ) + code = "" + +"try {\n" + + code + +"} finally {\n" + +" $luan.stackClear("+stackStart+","+stackEnd+");\n" + +"}\n" + ; + return new StmtString(code); } - private boolean StmtSep(List<Stmt> stmts) throws ParseException { + private boolean StmtSep(StringBuilder stmts) throws ParseException { parser.begin(); if( parser.match( ';' ) ) return parser.success(); if( EndOfLine() ) return parser.success(); parser.rollback(); - Stmt stmt = TemplateStmt(); + StmtString stmt = stmtStr(TemplateStmt()); if( stmt != null ) { - stmts.add(stmt); + stmts.append(stmt.code); return parser.success(); } return parser.failure(); @@ -235,23 +242,23 @@ return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' ); } - private void Stmt(List<Stmt> stmts) throws ParseException { + private void Stmt(StringBuilder stmts) throws ParseException { if( LocalStmt(stmts) ) return; - Stmt stmt; - if( (stmt=ReturnStmt()) != null - || (stmt=FunctionStmt()) != null - || (stmt=LocalFunctionStmt()) != null - || (stmt=BreakStmt()) != null - || (stmt=ForStmt()) != null + StmtString stmt; + if( (stmt=stmtStr(ReturnStmt())) != null + || (stmt=stmtStr(FunctionStmt())) != null + || (stmt=stmtStr(LocalFunctionStmt())) != null + || (stmt=stmtStr(BreakStmt())) != null + || (stmt=stmtStr(ForStmt())) != null || (stmt=DoStmt()) != null || (stmt=WhileStmt()) != null || (stmt=RepeatStmt()) != null - || (stmt=IfStmt()) != null - || (stmt=SetStmt()) != null + || (stmt=stmtStr(IfStmt())) != null + || (stmt=stmtStr(SetStmt())) != null || (stmt=ExpressionsStmt()) != null ) { - stmts.add(stmt); + stmts.append(stmt.code); } } @@ -358,23 +365,23 @@ Expr expr = expr(exp(RequiredExpr(In.NOTHING))); RequiredKeyword("do",In.NOTHING); addSymbols(names); - Stmt loop = RequiredLoopBlock(); + Stmt loop = stmt(RequiredLoopBlock()); RequiredKeyword("end",In.NOTHING); Stmt stmt = new ForStmt( stackStart, symbolsSize() - stackStart, expr, loop ); popSymbols( symbolsSize() - stackStart ); return parser.success(stmt); } - private Stmt DoStmt() throws ParseException { + private StmtString DoStmt() throws ParseException { parser.begin(); if( !Keyword("do",In.NOTHING) ) return parser.failure(null); - Stmt stmt = RequiredBlock(); + StmtString stmt = RequiredBlock(); RequiredKeyword("end",In.NOTHING); return parser.success(stmt); } - private boolean LocalStmt(List<Stmt> stmts) throws ParseException { + private boolean LocalStmt(StringBuilder stmts) throws ParseException { parser.begin(); if( !Keyword("local",In.NOTHING) ) return parser.failure(); @@ -394,7 +401,7 @@ for( int i=0; i<vars.length; i++ ) { vars[i] = new SetLocalVar(stackStart+i); } - stmts.add( new SetStmt( vars, values ) ); + stmts.append( new StmtString(new SetStmt( vars, values )).code ); } addSymbols(names); return parser.success(); @@ -431,30 +438,44 @@ return parser.success(name); } - private Stmt WhileStmt() throws ParseException { + private StmtString WhileStmt() throws ParseException { parser.begin(); if( !Keyword("while",In.NOTHING) ) return parser.failure(null); - Expr cnd = expr(exp(RequiredExpr(In.NOTHING))); + ExpString cnd = RequiredExpr(In.NOTHING).expr(); RequiredKeyword("do",In.NOTHING); - Stmt loop = RequiredLoopBlock(); + StmtString loop = RequiredLoopBlock(); RequiredKeyword("end",In.NOTHING); - return parser.success( new WhileStmt(cnd,loop) ); + String code = "" + +"try {\n" + +" while( $Luan.checkBoolean(" + cnd.code + ") ) {\n" + + loop.code + +" }\n" + +"} catch(BreakException e) {}\n" + ; + return parser.success( new StmtString(code) ); } - private Stmt RepeatStmt() throws ParseException { + private StmtString RepeatStmt() throws ParseException { parser.begin(); if( !Keyword("repeat",In.NOTHING) ) return parser.failure(null); - Stmt loop = RequiredLoopBlock(); + StmtString loop =RequiredLoopBlock(); RequiredKeyword("until",In.NOTHING); - Expr cnd = expr(exp(RequiredExpr(In.NOTHING))); - return parser.success( new RepeatStmt(loop,cnd) ); + ExpString cnd = RequiredExpr(In.NOTHING).expr(); + String code = "" + +"try {\n" + +" do {\n" + + loop.code + +" } while( !$Luan.checkBoolean(" + cnd.code + ") );\n" + +"} catch(BreakException e) {}\n" + ; + return parser.success( new StmtString(code) ); } - private Stmt RequiredLoopBlock() throws ParseException { + private StmtString RequiredLoopBlock() throws ParseException { incLoops(); - Stmt stmt = RequiredBlock(); + StmtString stmt = RequiredBlock(); decLoops(); return stmt; } @@ -470,12 +491,12 @@ parser.currentIndex(); Expr cnd = expr(exp(RequiredExpr(In.NOTHING))); RequiredKeyword("then",In.NOTHING); - Stmt thenBlock = RequiredBlock(); + Stmt thenBlock = stmt(RequiredBlock()); Stmt elseBlock; if( Keyword("elseif",In.NOTHING) ) { elseBlock = IfStmt2(); } else { - elseBlock = Keyword("else",In.NOTHING) ? RequiredBlock() : Stmt.EMPTY; + elseBlock = Keyword("else",In.NOTHING) ? stmt(RequiredBlock()) : Stmt.EMPTY; RequiredKeyword("end",In.NOTHING); } return new IfStmt(cnd,thenBlock,elseBlock); @@ -505,11 +526,16 @@ return parser.success( new SetStmt( vars.toArray(new Settable[0]), values ) ); } - private Stmt ExpressionsStmt() throws ParseException { + private StmtString ExpressionsStmt() throws ParseException { parser.begin(); - Expressions exp = exp(ExprZ(In.NOTHING)); - if( exp instanceof StmtExp ) - return parser.success( new ExpressionsStmt(exp) ); + ExpString exp = ExprZ(In.NOTHING); + if( exp != null && exp.isStmt ) { + String code = exp.code; + if( exp.isExpr ) + code = "$Luan.nop(" + code + ")"; + code += ";\n"; + return parser.success( new StmtString(code) ); + } return parser.failure(null); } @@ -772,7 +798,7 @@ } RequiredMatch(')'); Spaces(in); - Stmt block = RequiredBlock(); + Stmt block = stmt(RequiredBlock()); RequiredKeyword("end",in); FnDef fnDef = newFnDef(start,block); frame = frame.parent; @@ -1443,4 +1469,55 @@ return expStr==null ? null : expStr.toExpressions(); } + + private static class StmtString { + final String code; + + StmtString(Stmt stmt) { + if( stmt==null ) throw new NullPointerException(); + int i = $Luan.addStmt(stmt); + code = "$Luan.getStmt(" + i + ").eval($luan);\n"; + } + + StmtString(String code) { + this.code = code; + } + + Stmt toStmt() { + String className = "EXP" + ++classCounter; + String classCode = "" + +"package luan.impl;\n" + +"import luan.LuanException;\n" + +"\n" + +"public class " + className +" implements Stmt {\n" + +" @Override public void eval(LuanStateImpl $luan) throws LuanException {\n" + +" Object $cnd;\n" + +" " + code + +" }\n" + +"}\n" + ; +//System.out.println(code); + try { + Class cls = LuanJavaCompiler.compile("luan.impl."+className,code,classCode); + return (Stmt)cls.newInstance(); + } catch(ClassNotFoundException e) { + throw new RuntimeException(e); + } catch(InstantiationException e) { + throw new RuntimeException(e); + } catch(IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } + + private static StmtString EMPTY_STMT = new StmtString(""); + + private static Stmt stmt(StmtString stmtStr) { + return stmtStr==null ? null : stmtStr.toStmt(); + } + + private static StmtString stmtStr(Stmt stmt) { + return stmt==null ? null : new StmtString(stmt); + } + }
--- a/core/src/luan/impl/LuanStateImpl.java Thu Mar 31 22:43:51 2016 -0600 +++ b/core/src/luan/impl/LuanStateImpl.java Fri Apr 01 17:24:44 2016 -0600 @@ -12,7 +12,7 @@ import luan.DeepCloner; -final class LuanStateImpl extends LuanState { +public final class LuanStateImpl extends LuanState { private static class Frame { final Frame previousFrame; @@ -90,7 +90,7 @@ frame.stack[index] = value; } - void stackClear(int start,int end) { + public void stackClear(int start,int end) { frame.stackClear(start,end); }
--- a/core/src/luan/impl/Stmt.java Thu Mar 31 22:43:51 2016 -0600 +++ b/core/src/luan/impl/Stmt.java Fri Apr 01 17:24:44 2016 -0600 @@ -3,7 +3,7 @@ import luan.LuanException; -interface Stmt { +public interface Stmt { public void eval(LuanStateImpl luan) throws LuanException; static final Stmt EMPTY = new Stmt() {