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;
 }