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
diff -r d658eab7bf4c -r 140cc5191b7a core/src/luan/impl/$Luan.java
--- 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) {}
+
 }
diff -r d658eab7bf4c -r 140cc5191b7a core/src/luan/impl/LuanParser.java
--- 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);
+	}
+
 }
diff -r d658eab7bf4c -r 140cc5191b7a core/src/luan/impl/LuanStateImpl.java
--- 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);
 	}
 
diff -r d658eab7bf4c -r 140cc5191b7a core/src/luan/impl/Stmt.java
--- 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() {