diff core/src/luan/impl/LuanParser.java @ 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
line wrap: on
line diff
--- 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;
+		}
+
+	}
+
 }