changeset 666:2f449ccf54d2

use lists to assemble source
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 07 Apr 2016 23:36:56 -0600
parents 41f8fdbc3a0a
children 08966099aa6d
files core/src/luan/impl/LuanParser.java
diffstat 1 files changed, 334 insertions(+), 165 deletions(-) [+]
line wrap: on
line diff
--- a/core/src/luan/impl/LuanParser.java	Thu Apr 07 17:06:22 2016 -0600
+++ b/core/src/luan/impl/LuanParser.java	Thu Apr 07 23:36:56 2016 -0600
@@ -176,13 +176,13 @@
 
 	private FnDef newFnDef(int start,StmtString stmt) {
 		if( !stmt.hasReturn )
-			stmt = new StmtString( stmt.code + "return LuanFunction.NOTHING;\n" );
+			stmt.list.add( "return LuanFunction.NOTHING;\n" );
 		return toFnDef( stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) );
 	}
 
 	private ExpString newFnExpStr(int start,StmtString stmt) {
 		if( !stmt.hasReturn )
-			stmt = new StmtString( stmt.code + "return LuanFunction.NOTHING;\n" );
+			stmt.list.add( "return LuanFunction.NOTHING;\n" );
 		return toFnExpStr( stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) );
 	}
 
@@ -191,8 +191,10 @@
 		int start = parser.begin();
 		ExpString expr = ExprZ(In.NOTHING);
 		if( expr != null && parser.endOfInput() ) {
-			String code = "return " + expr.code + ";\n";
-			StmtString stmt = new StmtString(code);
+			StmtString stmt = new StmtString();
+			stmt.list.add( "return " );
+			stmt.list.addAll( expr.list );
+			stmt.list.add( ";\n" );
 			stmt.hasReturn = true;
 			return parser.success(newFnDef(start,stmt));
 		}
@@ -210,7 +212,7 @@
 	}
 
 	private StmtString RequiredBlock() throws ParseException {
-		StringBuilder stmts = new StringBuilder();
+		StmtString stmts = new StmtString();
 		int stackStart = symbolsSize();
 		boolean isReturn = Stmt(stmts);
 		while( !isReturn && StmtSep(stmts) ) {
@@ -221,23 +223,22 @@
 		Spaces(In.NOTHING);
 		int stackEnd = symbolsSize();
 		popSymbols( stackEnd - stackStart );
-		if( stmts.length() == 0 )
-			return EMPTY_STMT;
+		if( stmts.list.isEmpty() )
+			return stmts;
 		String code = stmts.toString();
-		if( stackStart < stackEnd )
-			code = ""
-				+"try {\n"
-				+ code
+		if( stackStart < stackEnd ) {
+			stmts.list.add( 0, "try {\n" );
+			stmts.list.add( ""
 				+"} finally {\n"
 				+"	luan.stackClear("+stackStart+","+stackEnd+");\n"
 				+"}\n"
-			;
-		StmtString stmt = new StmtString(code);
-		stmt.hasReturn = isReturn;
-		return stmt;
+			);
+		}
+		stmts.hasReturn = isReturn;
+		return stmts;
 	}
 
-	private boolean StmtSep(StringBuilder stmts) throws ParseException {
+	private boolean StmtSep(StmtString stmts) throws ParseException {
 		parser.begin();
 		if( parser.match( ';' ) )
 			return parser.success();
@@ -247,7 +248,7 @@
 //			parser.rollback();
 			StmtString stmt = TemplateStmt();
 			if( stmt != null ) {
-				stmts.append(stmt.code);
+				stmts.list.addAll(stmt.list);
 				return parser.success();
 			}
 		}
@@ -258,12 +259,12 @@
 		return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' );
 	}
 
-	private boolean Stmt(StringBuilder stmts) throws ParseException {
+	private boolean Stmt(StmtString stmts) throws ParseException {
 		if( LocalStmt(stmts) )
 			return false;
 		StmtString stmt;
 		if( (stmt=ReturnStmt()) != null ) {
-			stmts.append(stmt.code);
+			stmts.list.addAll(stmt.list);
 			return true;
 		}
 		if( (stmt=FunctionStmt()) != null
@@ -277,31 +278,44 @@
 			|| (stmt=SetStmt()) != null
 			|| (stmt=ExpressionsStmt()) != null
 		) {
-			stmts.append(stmt.code);
+			stmts.list.addAll(stmt.list);
 		}
 		return false;
 	}
 
 	private ExpString indexExpStr(ExpString exp1,ExpString exp2) {
-		String code = "luan.index(" + exp1.expr().code + "," + exp2.expr().code + ")";
-		return new ExpString(code,true,false);
+		ExpString exp = new ExpString(true,false);
+		exp.list.add( "luan.index(" );
+		exp.list.addAll( exp1.expr().list );
+		exp.list.add( "," );
+		exp.list.addAll( exp2.expr().list );
+		exp.list.add( ")" );
+		return exp;
 	}
 
 	private ExpString callExpStr(ExpString fn,ExpString args) {
-		String code = "Luan.checkFunction(" + fn.expr().code + ").call(luan,Luan.array(" + args.code + "))";
-		return new ExpString(code,false,true);
+		ExpString exp = new ExpString(false,true);
+		exp.list.add( "Luan.checkFunction(" );
+		exp.list.addAll( fn.expr().list );
+		exp.list.add( ").call(luan,Luan.array(" );
+		exp.list.addAll( args.list );
+		exp.list.add( "))" );
+		return exp;
 	}
 
 	private StmtString TemplateStmt() throws ParseException {
 		ExpString exprs = TemplateExpressions(In.NOTHING);
 		if( exprs == null )
 			return null;
-		String code = "PackageLuan.require(luan,\"luan:Io\")";
-		ExpString requireCall = new ExpString(code,true,false);
+		ExpString requireCall = new ExpString(true,false);
+		requireCall.list.add( "PackageLuan.require(luan,\"luan:Io\")" );
 		ExpString stdoutExp = indexExpStr( requireCall.expr(), constExpStr("stdout") );
 		ExpString writeExp = indexExpStr( stdoutExp, constExpStr("write") );
 		ExpString writeCall = callExpStr( writeExp, exprs );
-		return new StmtString( writeCall.code + ";\n" );
+		StmtString stmt = new StmtString();
+		stmt.list.addAll( writeCall.list );
+		stmt.list.add( ";\n" );
+		return stmt;
 	}
 
 	private ExpString TemplateExpressions(In in) throws ParseException {
@@ -340,8 +354,14 @@
 		if( !Keyword("return",In.NOTHING) )
 			return parser.failure(null);
 		ExpString exprs = ExpStringList(In.NOTHING);
-		String code = "return " + (exprs!=null ? exprs.code : "LuanFunction.NOTHING") + ";\n";
-		return parser.success( new StmtString(code) );
+		StmtString stmt = new StmtString();
+		stmt.list.add( "return " );
+		if( exprs != null )
+			stmt.list.addAll( exprs.list );
+		else
+			stmt.list.add( "LuanFunction.NOTHING" );
+		stmt.list.add( ";\n" );
+		return parser.success( stmt );
 	}
 
 	private StmtString FunctionStmt() throws ParseException {
@@ -371,8 +391,12 @@
 		addSymbol( name );
 		ExpString fnDef = RequiredFunction(In.NOTHING);
 		Settable s = new SetLocalVar(symbolsSize()-1);
-		String code = new SettableString(s).code + ".set(luan," + fnDef.code + ");\n";
-		return parser.success( new StmtString(code) );
+		StmtString stmt = new StmtString();
+		stmt.list.add( settableToString(s) );
+		stmt.list.add( ".set(luan," );
+		stmt.list.addAll( fnDef.list );
+		stmt.list.add( ");\n" );
+		return parser.success( stmt );
 	}
 
 	private StmtString BreakStmt() throws ParseException {
@@ -381,7 +405,9 @@
 			return parser.failure(null);
 		if( frame.loops <= 0 )
 			throw parser.exception("'break' outside of loop");
-		return parser.success( new StmtString("break;\n") );
+		StmtString stmt = new StmtString();
+		stmt.list.add( "break;\n" );
+		return parser.success( stmt );
 	}
 
 	int forCounter = 0;
@@ -408,22 +434,30 @@
 		StmtString loop = RequiredLoopBlock();
 		RequiredKeyword("end",In.NOTHING);
 		String fnVar = "fn"+ ++forCounter;
-		String code = ""
+		StmtString stmt = new StmtString();
+		stmt.list.add( ""
 			+"try {\n"
-			+"LuanFunction "+fnVar+" = Luan.checkFunction(" + expr.code + ");\n"
+			+"LuanFunction "+fnVar+" = Luan.checkFunction("
+		);
+		stmt.list.addAll( expr.list );
+		stmt.list.add( ""
+			+ ");\n"
 			+"while(true) {\n"
 			+"for( int i="+stackStart+"; i<"+symbolsSize()+"; i++ ) {\n"
 			+"luan.stackSet(i,null);\n"
 			+"}\n"
 			+"LuanImpl.set(luan," + varsStr + ", "+fnVar+".call(luan) );\n"
-			+"if( " + firstVar.code + "==null )  break;\n"
-			+ loop.code
+			+"if( "
+		);
+		stmt.list.addAll( firstVar.list );
+ 		stmt.list.add( "==null )  break;\n" );
+		stmt.list.addAll( loop.list );
+		stmt.list.add( ""
 			+"}"
 			+"} finally {\n"
 			+"luan.stackClear("+stackStart+","+symbolsSize()+");\n"
 			+"}\n"
-		;
-		StmtString stmt = new StmtString(code);
+		);
 		popSymbols( symbolsSize() - stackStart );
 		return parser.success(stmt);
 	}
@@ -437,7 +471,7 @@
 		return parser.success(stmt);
 	}
 
-	private boolean LocalStmt(StringBuilder stmts) throws ParseException {
+	private boolean LocalStmt(StmtString stmts) throws ParseException {
 		parser.begin();
 		if( !Keyword("local",In.NOTHING) )
 			return parser.failure();
@@ -458,8 +492,9 @@
 				vars[i] = new SetLocalVar(stackStart+i);
 			}
 			String varsStr = varsToString(vars);
-			String code = "LuanImpl.set(luan," + varsStr + "," + values.code + ");\n";
-			stmts.append(code);
+			stmts.list.add( "LuanImpl.set(luan," + varsStr + "," );
+			stmts.list.addAll( values.list );
+			stmts.list.add( ");\n" );
 		}
 		addSymbols(names);
 		return parser.success();
@@ -504,12 +539,13 @@
 		RequiredKeyword("do",In.NOTHING);
 		StmtString loop = RequiredLoopBlock();
 		RequiredKeyword("end",In.NOTHING);
-		String code = ""
-			+"while( Luan.checkBoolean(" + cnd.code + ") ) {\n"
-			+ loop.code
-			+"}\n"
-		;
-		return parser.success( new StmtString(code) );
+		StmtString stmt = new StmtString();
+		stmt.list.add( "while( Luan.checkBoolean(" );
+		stmt.list.addAll( cnd.list );
+		stmt.list.add( ") ) {\n" );
+		stmt.list.addAll( loop.list );
+		stmt.list.add( "}\n" );
+		return parser.success( stmt );
 	}
 
 	private StmtString RepeatStmt() throws ParseException {
@@ -519,12 +555,13 @@
 		StmtString loop =RequiredLoopBlock();
 		RequiredKeyword("until",In.NOTHING);
 		ExpString cnd = RequiredExpr(In.NOTHING).expr();
-		String code = ""
-			+"do {\n"
-			+ loop.code
-			+"} while( !Luan.checkBoolean(" + cnd.code + ") );\n"
-		;
-		return parser.success( new StmtString(code) );
+		StmtString stmt = new StmtString();
+		stmt.list.add( "do {\n" );
+		stmt.list.addAll( loop.list );
+		stmt.list.add( "} while( !Luan.checkBoolean(" );
+		stmt.list.addAll( cnd.list );
+		stmt.list.add( ") );\n" );
+		return parser.success( stmt );
 	}
 
 	private StmtString RequiredLoopBlock() throws ParseException {
@@ -538,26 +575,33 @@
 		parser.begin();
 		if( !Keyword("if",In.NOTHING) )
 			return parser.failure(null);
-		StringBuilder sb = new StringBuilder();
+		StmtString stmt = new StmtString();
 		ExpString cnd;
 		StmtString block;
 		cnd = RequiredExpr(In.NOTHING).expr();
 		RequiredKeyword("then",In.NOTHING);
 		block = RequiredBlock();
-		sb.append( "if( Luan.checkBoolean(" ).append( cnd.code ).append( ") ) {\n" ).append( block.code );
+		stmt.list.add( "if( Luan.checkBoolean(" );
+		stmt.list.addAll( cnd.list );
+		stmt.list.add( ") ) {\n" );
+		stmt.list.addAll( block.list );
 		while( Keyword("elseif",In.NOTHING) ) {
 			cnd = RequiredExpr(In.NOTHING).expr();
 			RequiredKeyword("then",In.NOTHING);
 			block = RequiredBlock();
-			sb.append( "} else if( Luan.checkBoolean(" ).append( cnd.code ).append( ") ) {\n" ).append( block.code );
+			stmt.list.add( "} else if( Luan.checkBoolean(" );
+			stmt.list.addAll( cnd.list );
+			stmt.list.add( ") ) {\n" );
+			stmt.list.addAll( block.list );
 		}
 		if( Keyword("else",In.NOTHING) ) {
 			block = RequiredBlock();
-			sb.append( "} else {\n" ).append( block.code );
+			stmt.list.add( "} else {\n" );
+			stmt.list.addAll( block.list );
 		}
 		RequiredKeyword("end",In.NOTHING);
-		sb.append( "}\n" );
-		return parser.success( new StmtString(sb.toString()) );
+		stmt.list.add( "}\n" );
+		return parser.success( stmt );
 	}
 
 	private StmtString SetStmt() throws ParseException {
@@ -584,21 +628,26 @@
 		int n = vars.size();
 		if( n == 1 )
 			return parser.success( vars.get(0).set(values) );
-		StringBuilder sb = new StringBuilder();
-		sb.append( "t = " + values.code + ";\n" );
-		ExpString t = new ExpString("t",true,false);
-		sb.append( vars.get(0).set(new ExpString("t",true,false)).code );
+		StmtString stmt = new StmtString();
+		stmt.list.add( "t = " );
+		stmt.list.addAll( values.list );
+		stmt.list.add( ";\n" );
+		ExpString t = new ExpString(true,false);
+		t.list.add( "t" );
+		stmt.list.addAll( vars.get(0).set(t).list );
 		for( int i=1; i<n; i++ ) {
-			sb.append( vars.get(i).set(new ExpString("LuanImpl.pick(t,"+i+")",true,false)).code );
+			t.list.clear();
+			t.list.add( "LuanImpl.pick(t,"+i+")" );
+			stmt.list.addAll( vars.get(i).set(t).list );
 		}
-		return parser.success( new StmtString(sb.toString()) );
+		return parser.success( stmt );
 	}
 
 	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( settableToString(v) ).append( ',' );
 		}
 		sb.append( "}" );
 		return sb.toString();
@@ -608,11 +657,16 @@
 		parser.begin();
 		ExpString exp = ExprZ(In.NOTHING);
 		if( exp != null && exp.isStmt ) {
-			String code = exp.code;
-			if( exp.isExpr )
-				code = "LuanImpl.nop(" + code + ")";
-			code += ";\n";
-			return parser.success( new StmtString(code) );
+			StmtString stmt = new StmtString();
+			if( exp.isExpr ) {
+				stmt.list.add( "LuanImpl.nop(" );
+				stmt.list.addAll( exp.list );
+				stmt.list.add( ")" );
+			} else {
+				stmt.list.addAll( exp.list );
+			}
+			stmt.list.add( ";\n" );
+			return parser.success( stmt );
 		}
 		return parser.failure(null);
 	}
@@ -642,8 +696,13 @@
 		while( Keyword("or",in) ) {
 			exp = exp.expr();
 			ExpString exp2 = required(RelExpr(in)).expr();
-			String code = "(LuanImpl.cnd(t = " + exp.code + ") ? t : (" + exp2.code + "))";
-			exp = new ExpString(code,true,true);
+			ExpString newExp = new ExpString(true,true);
+			newExp.list.add( "(LuanImpl.cnd(t = " );
+			newExp.list.addAll( exp.list );
+			newExp.list.add( ") ? t : (" );
+			newExp.list.addAll( exp2.list );
+			newExp.list.add( "))" );
+			exp = newExp;
 		}
 		return parser.success(exp);
 	}
@@ -656,8 +715,13 @@
 		while( Keyword("and",in) ) {
 			exp = exp.expr();
 			ExpString exp2 = required(RelExpr(in)).expr();
-			String code = "(LuanImpl.cnd(t = " + exp.code + ") ? (" + exp2.code + ") : t)";
-			exp = new ExpString(code,true,true);
+			ExpString newExp = new ExpString(true,true);
+			newExp.list.add( "(LuanImpl.cnd(t = " );
+			newExp.list.addAll( exp.list );
+			newExp.list.add( ") ? (" );
+			newExp.list.addAll( exp2.list );
+			newExp.list.add( ") : t)" );
+			exp = newExp;
 		}
 		return parser.success(exp);
 	}
@@ -672,38 +736,68 @@
 				Spaces(in);
 				exp = exp.expr();
 				ExpString exp2 = required(ConcatExpr(in)).expr();
-				String code = "LuanImpl.eq(luan," + exp.code + "," + exp2.code + ")";
-				exp = new ExpString(code,true,false);
+				ExpString newExp = new ExpString(true,false);
+				newExp.list.add( "LuanImpl.eq(luan," );
+				newExp.list.addAll( exp.list );
+				newExp.list.add( "," );
+				newExp.list.addAll( exp2.list );
+				newExp.list.add( ")" );
+				exp = newExp;
 			} else if( parser.match("~=") ) {
 				Spaces(in);
 				exp = exp.expr();
 				ExpString exp2 = required(ConcatExpr(in)).expr();
-				String code = "!LuanImpl.eq(luan," + exp.code + "," + exp2.code + ")";
-				exp = new ExpString(code,true,false);
+				ExpString newExp = new ExpString(true,false);
+				newExp.list.add( "!LuanImpl.eq(luan," );
+				newExp.list.addAll( exp.list );
+				newExp.list.add( "," );
+				newExp.list.addAll( exp2.list );
+				newExp.list.add( ")" );
+				exp = newExp;
 			} else if( parser.match("<=") ) {
 				Spaces(in);
 				exp = exp.expr();
 				ExpString exp2 = required(ConcatExpr(in)).expr();
-				String code = "LuanImpl.le(luan," + exp.code + "," + exp2.code + ")";
-				exp = new ExpString(code,true,false);
+				ExpString newExp = new ExpString(true,false);
+				newExp.list.add( "LuanImpl.le(luan," );
+				newExp.list.addAll( exp.list );
+				newExp.list.add( "," );
+				newExp.list.addAll( exp2.list );
+				newExp.list.add( ")" );
+				exp = newExp;
 			} else if( parser.match(">=") ) {
 				Spaces(in);
 				exp = exp.expr();
 				ExpString exp2 = required(ConcatExpr(in)).expr();
-				String code = "LuanImpl.le(luan," + exp2.code + "," + exp.code + ")";
-				exp = new ExpString(code,true,false);
+				ExpString newExp = new ExpString(true,false);
+				newExp.list.add( "LuanImpl.le(luan," );
+				newExp.list.addAll( exp2.list );
+				newExp.list.add( "," );
+				newExp.list.addAll( exp.list );
+				newExp.list.add( ")" );
+				exp = newExp;
 			} else if( parser.match("<") ) {
 				Spaces(in);
 				exp = exp.expr();
 				ExpString exp2 = required(ConcatExpr(in)).expr();
-				String code = "LuanImpl.lt(luan," + exp.code + "," + exp2.code + ")";
-				exp = new ExpString(code,true,false);
-		} else if( parser.match(">") ) {
+				ExpString newExp = new ExpString(true,false);
+				newExp.list.add( "LuanImpl.lt(luan," );
+				newExp.list.addAll( exp.list );
+				newExp.list.add( "," );
+				newExp.list.addAll( exp2.list );
+				newExp.list.add( ")" );
+				exp = newExp;
+			} else if( parser.match(">") ) {
 				Spaces(in);
 				exp = exp.expr();
 				ExpString exp2 = required(ConcatExpr(in)).expr();
-				String code = "LuanImpl.lt(luan," + exp2.code + "," + exp.code + ")";
-				exp = new ExpString(code,true,false);
+				ExpString newExp = new ExpString(true,false);
+				newExp.list.add( "LuanImpl.lt(luan," );
+				newExp.list.addAll( exp2.list );
+				newExp.list.add( "," );
+				newExp.list.addAll( exp.list );
+				newExp.list.add( ")" );
+				exp = newExp;
 			} else
 				break;
 		}
@@ -719,8 +813,13 @@
 			Spaces(in);
 			exp = exp.expr();
 			ExpString exp2 = required(ConcatExpr(in)).expr();
-			String code = "LuanImpl.concat(luan," + exp.code + "," + exp2.code + ")";
-			exp = new ExpString(code,true,false);
+			ExpString newExp = new ExpString(true,false);
+			newExp.list.add( "LuanImpl.concat(luan," );
+			newExp.list.addAll( exp.list );
+			newExp.list.add( "," );
+			newExp.list.addAll( exp2.list );
+			newExp.list.add( ")" );
+			exp = newExp;
 		}
 		return parser.success(exp);
 	}
@@ -735,14 +834,24 @@
 				Spaces(in);
 				exp = exp.expr();
 				ExpString exp2 = required(TermExpr(in)).expr();
-				String code = "LuanImpl.add(luan," + exp.code + "," + exp2.code + ")";
-				exp = new ExpString(code,true,false);
+				ExpString newExp = new ExpString(true,false);
+				newExp.list.add( "LuanImpl.add(luan," );
+				newExp.list.addAll( exp.list );
+				newExp.list.add( "," );
+				newExp.list.addAll( exp2.list );
+				newExp.list.add( ")" );
+				exp = newExp;
 			} else if( Minus() ) {
 				Spaces(in);
 				exp = exp.expr();
 				ExpString exp2 = required(TermExpr(in)).expr();
-				String code = "LuanImpl.sub(luan," + exp.code + "," + exp2.code + ")";
-				exp = new ExpString(code,true,false);
+				ExpString newExp = new ExpString(true,false);
+				newExp.list.add( "LuanImpl.sub(luan," );
+				newExp.list.addAll( exp.list );
+				newExp.list.add( "," );
+				newExp.list.addAll( exp2.list );
+				newExp.list.add( ")" );
+				exp = newExp;
 			} else
 				break;
 		}
@@ -764,20 +873,35 @@
 				Spaces(in);
 				exp = exp.expr();
 				ExpString exp2 = required(UnaryExpr(in)).expr();
-				String code = "LuanImpl.mul(luan," + exp.code + "," + exp2.code + ")";
-				exp = new ExpString(code,true,false);
+				ExpString newExp = new ExpString(true,false);
+				newExp.list.add( "LuanImpl.mul(luan," );
+				newExp.list.addAll( exp.list );
+				newExp.list.add( "," );
+				newExp.list.addAll( exp2.list );
+				newExp.list.add( ")" );
+				exp = newExp;
 			} else if( parser.match('/') ) {
 				Spaces(in);
 				exp = exp.expr();
 				ExpString exp2 = required(UnaryExpr(in)).expr();
-				String code = "LuanImpl.div(luan," + exp.code + "," + exp2.code + ")";
-				exp = new ExpString(code,true,false);
+				ExpString newExp = new ExpString(true,false);
+				newExp.list.add( "LuanImpl.div(luan," );
+				newExp.list.addAll( exp.list );
+				newExp.list.add( "," );
+				newExp.list.addAll( exp2.list );
+				newExp.list.add( ")" );
+				exp = newExp;
 			} else if( Mod() ) {
 				Spaces(in);
 				exp = exp.expr();
 				ExpString exp2 = required(UnaryExpr(in)).expr();
-				String code = "LuanImpl.mod(luan," + exp.code + "," + exp2.code + ")";
-				exp = new ExpString(code,true,false);
+				ExpString newExp = new ExpString(true,false);
+				newExp.list.add( "LuanImpl.mod(luan," );
+				newExp.list.addAll( exp.list );
+				newExp.list.add( "," );
+				newExp.list.addAll( exp2.list );
+				newExp.list.add( ")" );
+				exp = newExp;
 			} else
 				break;
 		}
@@ -794,23 +918,29 @@
 		if( parser.match('#') ) {
 			Spaces(in);
 			ExpString exp = required(UnaryExpr(in)).expr();
-			String code = "LuanImpl.len(luan," + exp.code + ")";
-			exp = new ExpString(code,true,false);
-			return parser.success(exp);
+			ExpString newExp = new ExpString(true,false);
+			newExp.list.add( "LuanImpl.len(luan," );
+			newExp.list.addAll( exp.list );
+			newExp.list.add( ")" );
+			return parser.success(newExp);
 		}
 		if( Minus() ) {
 			Spaces(in);
 			ExpString exp = required(UnaryExpr(in)).expr();
-			String code = "LuanImpl.unm(luan," + exp.code + ")";
-			exp = new ExpString(code,true,false);
-			return parser.success(exp);
+			ExpString newExp = new ExpString(true,false);
+			newExp.list.add( "LuanImpl.unm(luan," );
+			newExp.list.addAll( exp.list );
+			newExp.list.add( ")" );
+			return parser.success(newExp);
 		}
 		if( Keyword("not",in) ) {
 			Spaces(in);
 			ExpString exp = required(UnaryExpr(in)).expr();
-			String code = "!Luan.checkBoolean(" + exp.code + ")";
-			exp = new ExpString(code,true,false);
-			return parser.success(exp);
+			ExpString newExp = new ExpString(true,false);
+			newExp.list.add( "!Luan.checkBoolean(" );
+			newExp.list.addAll( exp.list );
+			newExp.list.add( ")" );
+			return parser.success(newExp);
 		}
 		ExpString exp = PowExpr(in);
 		if( exp==null )
@@ -826,8 +956,13 @@
 		if( parser.match('^') ) {
 			Spaces(in);
 			ExpString exp2 = required(PowExpr(in));
-			String code = "LuanImpl.pow(luan," + exp1.code + "," + exp2.code + ")";
-			exp1 = new ExpString(code,true,false);
+			ExpString newExp = new ExpString(true,false);
+			newExp.list.add( "LuanImpl.pow(luan," );
+			newExp.list.addAll( exp1.expr().list );
+			newExp.list.add( "," );
+			newExp.list.addAll( exp2.expr().list );
+			newExp.list.add( ")" );
+			exp1 = newExp;
 		}
 		return parser.success(exp1);
 	}
@@ -906,8 +1041,11 @@
 		if( !parser.match('}') )
 			throw parser.exception("Expected table element or '}'");
 		Spaces(in);
-		String code = "LuanImpl.table(" + expString(builder).code + ")";
-		return parser.success( new ExpString(code,true,false) );
+		exp = new ExpString(true,false);
+		exp.list.add( "LuanImpl.table(" );
+		exp.list.addAll( expString(builder).list );
+		exp.list.add( ")" );
+		return parser.success( exp );
 	}
 
 	private boolean FieldSep() throws ParseException {
@@ -922,8 +1060,13 @@
 		if( exp!=null && parser.match('=') ) {
 			Spaces(In.NOTHING);
 			ExpString val = RequiredExpr(In.NOTHING).expr();
-			String code = "new TableField(" + exp.code + "," + val.code + ")";
-			builder.add( new ExpString(code,true,false) );
+			ExpString newExp = new ExpString(true,false);
+			newExp.list.add( "new TableField(" );
+			newExp.list.addAll( exp.list );
+			newExp.list.add( "," );
+			newExp.list.addAll( val.list );
+			newExp.list.add( ")" );
+			builder.add( newExp );
 			return parser.success();
 		}
 		parser.rollback();
@@ -1045,8 +1188,11 @@
 			}
 
 			public StmtString set(ExpString val) throws ParseException {
-				String code = new SettableString(settable()).code + ".set(luan," + val.expr().code + ");\n";
-				return new StmtString(code);
+				StmtString stmt = new StmtString();
+				stmt.list.add( settableToString(settable()) + ".set(luan," );
+				stmt.list.addAll( val.expr().list );
+				stmt.list.add( ");\n" );
+				return stmt;
 			}
 		};
 	}
@@ -1084,8 +1230,15 @@
 			}
 */
 			public StmtString set(ExpString val) {
-				String code = "LuanImpl.put(luan," + table.expr().code + "," + key.expr().code + "," + val.expr().code + ");\n";
-				return new StmtString(code);
+				StmtString stmt = new StmtString();
+				stmt.list.add( "LuanImpl.put(luan," );
+				stmt.list.addAll( table.expr().list );
+				stmt.list.add( "," );
+				stmt.list.addAll( key.expr().list );
+				stmt.list.add( "," );
+				stmt.list.addAll( val.expr().list );
+				stmt.list.add( ");\n" );
+				return stmt;
 			}
 		};
 	}
@@ -1253,17 +1406,25 @@
 
 	private ExpString Literal(In in) throws ParseException {
 		parser.begin();
-		if( NilLiteral(in) )
-			return parser.success(new ExpString("null",true,false));
+		if( NilLiteral(in) ) {
+			ExpString exp = new ExpString(true,false);
+			exp.list.add( "null" );
+			return parser.success(exp);
+		}
 		Boolean b = BooleanLiteral(in);
-		if( b != null )
-			return parser.success(new ExpString(b.toString(),true,false));
+		if( b != null ) {
+			ExpString exp = new ExpString(true,false);
+			exp.list.add( b.toString() );
+			return parser.success(exp);
+		}
 		Number n = NumberLiteral(in);
 		if( n != null ) {
 			String s = n.toString();
 			if( n instanceof Long )
 				s += "L";
-			return parser.success(new ExpString(s,true,false));
+			ExpString exp = new ExpString(true,false);
+			exp.list.add( s );
+			return parser.success(exp);
 		}
 		String s = StringLiteral(in);
 		if( s != null )
@@ -1280,7 +1441,9 @@
 			.replace("\t","\\t")
 			.replace("\b","\\b")
 		;
-		return new ExpString( "\""+s+"\"", true,false);
+		ExpString exp = new ExpString(true,false);
+		exp.list.add( "\""+s+"\"" );
+		return exp;
 	}
 
 	private boolean NilLiteral(In in) throws ParseException {
@@ -1533,67 +1696,78 @@
 	private static int classCounter = 0;
 
 	private class ExpString {
-		final String code;
+		final List list = new ArrayList();
 		final boolean isExpr;
 		final boolean isStmt;
 
 		ExpString(Expressions exp) {
 			if( exp==null )  throw new NullPointerException();
 			int i = LuanImpl.addObj(exp);
-			code = "((Expressions)LuanImpl.getObj(" + i + ")).eval(luan)";
+			list.add( "((Expressions)LuanImpl.getObj(" + i + ")).eval(luan)" );
 			isExpr = exp instanceof Expr;
 			isStmt = exp instanceof StmtExp;
 		}
 
-		ExpString(String code,boolean isExpr,boolean isStmt) {
-			this.code = code;
+		ExpString(boolean isExpr,boolean isStmt) {
 			this.isExpr = isExpr;
 			this.isStmt = isStmt;
 		}
 
 		ExpString expr() {
-			return isExpr ? this : new ExpString( "Luan.first(" + code + ")", true, isStmt );
+			if( isExpr )
+				return this;
+			ExpString exp = new ExpString(true,isStmt);
+			exp.list.addAll( list );
+			return exp;
 		}
 	}
 
 	private ExpString expString(List<ExpString> list) {
+		ExpString exp = new ExpString(false,false);
 		switch(list.size()) {
 		case 0:
-			return new ExpString("LuanFunction.NOTHING",false,false);
+			exp.list.add("LuanFunction.NOTHING");
+			return exp;
 		case 1:
 			return list.get(0);
 		default:
 			int lastI = list.size() - 1;
-			StringBuilder sb = new StringBuilder();
-			sb.append( "new Object[]{" );
+			exp.list.add( "new Object[]{" );
 			for( int i=0; i<lastI; i++ ) {
-				sb.append( list.get(i).expr().code ).append( ',' );
+				exp.list.addAll( list.get(i).expr().list );
+				exp.list.add( "," );
 			}
 			ExpString last = list.get(lastI);
 			if( last.isExpr ) {
-				sb.append( last.code ).append( '}' );
-				return new ExpString(sb.toString(),false,false);
+				exp.list.addAll( last.list );
+				exp.list.add( "}" );
 			} else {
-				sb.append( '}' );
-				String s = "LuanImpl.concatArgs(" + sb + "," + last.code + ")";
-				return new ExpString(s,false,false);
+				exp.list.add( "}" );
+				exp.list.add( 0, "LuanImpl.concatArgs(" );
+				exp.list.add( "," );
+				exp.list.addAll( last.list );
+				exp.list.add( ")" );
 			}
+			return exp;
 		}
 	}
 
 	private static class StmtString {
-		final String code;
+		final List list = new ArrayList();
 		boolean hasReturn = false;
-
-		StmtString(String code) {
-			this.code = code;
-			if( code.contains("LuanParser") )  throw new RuntimeException("\n"+code);
-		}
 	}
 
-	private static StmtString EMPTY_STMT = new StmtString("");
+	private static FnDef toFnDef(StmtString stmt,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) {
+		StringBuilder sb = new StringBuilder();
+		for( Object o : stmt.list ) {
+			if( o instanceof List )  throw new RuntimeException();
+			if( o instanceof ExpString )  throw new RuntimeException();
+			if( o instanceof StmtString )  throw new RuntimeException();
+			sb.append( o.toString() );
+		}
+		String code = sb.toString();
+//System.out.println("code:\n"+code);
 
-	private static FnDef toFnDef(StmtString stmt,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) {
 		int i = LuanImpl.addObj(upValueGetters);
 		String className = "EXP" + ++classCounter;
 		String classCode = ""
@@ -1610,7 +1784,7 @@
 			+"\n"
 			+"	@Override public Object run(LuanStateImpl luan) throws LuanException {\n"
 			+"		Object t;\n"
-			+"		" + stmt.code
+			+"		" + code
 			+"	}\n"
 			+"}\n"
 		;
@@ -1629,32 +1803,27 @@
 
 	private ExpString toFnExpStr(StmtString stmt,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) {
 		int i = LuanImpl.addObj(upValueGetters);
-		String classCode = ""
+		ExpString exp = new ExpString(true,false);
+		exp.list.add( ""
 			+"\n"
 			+"new FnDef("+stackSize+","+numArgs+","+isVarArg+",(UpValue.Getter[])LuanImpl.getObj("+i+")) {\n"
 			+"	@Override public Object run(LuanStateImpl luan) throws LuanException {\n"
 			+"		Object t;\n"
-			+"		" + stmt.code
+			+"		"
+		);
+		exp.list.addAll( stmt.list );
+		exp.list.add( ""
 			+"	}\n"
 			+"}.eval(luan)\n"
-		;
-		return new ExpString(classCode,true,false);
+		);
+		return exp;
 	}
 
 
-	private static class SettableString {
-		final String code;
-
-		SettableString(Settable settable) {
-			if( settable==null )  throw new NullPointerException();
-			int i = LuanImpl.addObj(settable);
-			code = "((Settable)LuanImpl.getObj(" + i + "))";
-		}
-
-		SettableString(String code) {
-			this.code = code;
-		}
-
+	private static String settableToString(Settable settable) {
+		if( settable==null )  throw new NullPointerException();
+		int i = LuanImpl.addObj(settable);
+		return"((Settable)LuanImpl.getObj(" + i + "))";
 	}
 
 }