changeset 677:5c85d38659db

minor
author Franklin Schmidt <fschmidt@gmail.com>
date Wed, 13 Apr 2016 14:23:06 -0600
parents 1b6a0dc0ea16
children 49f3d290bebd
files core/src/luan/impl/LuanParser.java
diffstat 1 files changed, 255 insertions(+), 258 deletions(-) [+]
line wrap: on
line diff
diff -r 1b6a0dc0ea16 -r 5c85d38659db core/src/luan/impl/LuanParser.java
--- a/core/src/luan/impl/LuanParser.java	Tue Apr 12 19:44:32 2016 -0600
+++ b/core/src/luan/impl/LuanParser.java	Wed Apr 13 14:23:06 2016 -0600
@@ -33,7 +33,7 @@
 		Stmts declaration(Expr value) {
 			Stmts stmt = new Stmts();
 			if( value==null ) {
-				stmt.list.add( new Object() {
+				stmt.add( new Object() {
 					@Override public String toString() {
 						if( !isPointer )
 							return "Object " + javaName + ";\n";
@@ -43,7 +43,7 @@
 				} );
 			} else {
 				if( value.valType != Val.SINGLE )  throw new RuntimeException();
-				stmt.list.add( new Object() {
+				stmt.add( new Object() {
 					@Override public String toString() {
 						if( !isPointer )
 							return "Object " + javaName + " = ";
@@ -51,8 +51,8 @@
 							return "final Pointer " + javaName + " = new Pointer(";
 					}
 				} );
-				stmt.list.addAll(value.list);
-				stmt.list.add( new Object() {
+				stmt.addAll(value);
+				stmt.add( new Object() {
 					@Override public String toString() {
 						if( !isPointer )
 							return ";\n";
@@ -66,7 +66,7 @@
 
 		@Override public Expr exp() {
 			Expr exp = new Expr(Val.SINGLE,false);
-			exp.list.add( new Object() {
+			exp.add( new Object() {
 				@Override public String toString() {
 					if( !isPointer )
 						return javaName;
@@ -95,7 +95,7 @@
 
 		@Override public Expr exp() {
 			Expr exp = new Expr(Val.SINGLE,false);
-			exp.list.add( new Object() {
+			exp.add( new Object() {
 				@Override public String toString() {
 					return "upValues[" + i + "].o";
 				}
@@ -199,7 +199,7 @@
 		if( name != null ) {
 			LocalSym sym = frame.addLocalSym( name );
 			sym.isPointer = true;
-			top.list.add( "final Pointer " + sym.javaName + " = upValues[" + upSym.i + "];\n" );
+			top.add( "final Pointer " + sym.javaName + " = upValues[" + upSym.i + "];\n" );
 		}
 	}
 
@@ -245,13 +245,13 @@
 
 	private Class newFnClass(int start,Stmts stmt) {
 		if( !stmt.hasReturn )
-			stmt.list.add( "return LuanFunction.NOTHING;\n" );
+			stmt.add( "return LuanFunction.NOTHING;\n" );
 		return toFnClass( stmt, frame.upValueSymbols );
 	}
 
 	private Expr newFnExpStr(int start,Stmts stmt) {
 		if( !stmt.hasReturn )
-			stmt.list.add( "return LuanFunction.NOTHING;\n" );
+			stmt.add( "return LuanFunction.NOTHING;\n" );
 		return toFnExpStr( stmt, frame.upValueSymbols );
 	}
 
@@ -260,9 +260,9 @@
 		int start = parser.begin();
 		Expr expr = ExprZ(In.NOTHING);
 		if( expr != null && parser.endOfInput() ) {
-			top.list.add( "return " );
-			top.list.addAll( expr.list );
-			top.list.add( ";\n" );
+			top.add( "return " );
+			top.addAll( expr );
+			top.add( ";\n" );
 			top.hasReturn = true;
 			return parser.success(newFnClass(start,top));
 		}
@@ -273,9 +273,9 @@
 		Spaces(In.NOTHING);
 		int start = parser.begin();
 		frame.isVarArg = true;
-		top.list.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" );
+		top.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" );
 		Stmts block = RequiredBlock();
-		top.list.addAll( block.list );
+		top.addAll( block );
 		top.hasReturn = block.hasReturn;
 		if( parser.endOfInput() )
 			return parser.success(newFnClass(start,top));
@@ -308,7 +308,7 @@
 //			parser.rollback();
 			Stmts stmt = TemplateStmt();
 			if( stmt != null ) {
-				stmts.list.addAll(stmt.list);
+				stmts.addAll(stmt);
 				return parser.success();
 			}
 		}
@@ -322,7 +322,7 @@
 	private boolean Stmt(Stmts stmts) throws ParseException {
 		Stmts stmt;
 		if( (stmt=ReturnStmt()) != null ) {
-			stmts.list.addAll(stmt.list);
+			stmts.addAll(stmt);
 			return true;
 		}
 		if( (stmt=FunctionStmt()) != null
@@ -337,28 +337,28 @@
 			|| (stmt=SetStmt()) != null
 			|| (stmt=ExpressionsStmt()) != null
 		) {
-			stmts.list.addAll(stmt.list);
+			stmts.addAll(stmt);
 		}
 		return false;
 	}
 
 	private Expr indexExpStr(Expr exp1,Expr exp2) {
 		Expr exp = new Expr(Val.SINGLE,false);
-		exp.list.add( "luan.index(" );
-		exp.list.addAll( exp1.single().list );
-		exp.list.add( "," );
-		exp.list.addAll( exp2.single().list );
-		exp.list.add( ")" );
+		exp.add( "luan.index(" );
+		exp.addAll( exp1.single() );
+		exp.add( "," );
+		exp.addAll( exp2.single() );
+		exp.add( ")" );
 		return exp;
 	}
 
 	private Expr callExpStr(Expr fn,Expr args) {
 		Expr exp = new Expr(null,true);
-		exp.list.add( "Luan.checkFunction(" );
-		exp.list.addAll( fn.single().list );
-		exp.list.add( ").call(luan," );
-		exp.list.addAll( args.array().list );
-		exp.list.add( ")" );
+		exp.add( "Luan.checkFunction(" );
+		exp.addAll( fn.single() );
+		exp.add( ").call(luan," );
+		exp.addAll( args.array() );
+		exp.add( ")" );
 		return exp;
 	}
 
@@ -367,13 +367,13 @@
 		if( exprs == null )
 			return null;
 		Expr requireCall = new Expr(Val.SINGLE,false);
-		requireCall.list.add( "PackageLuan.require(luan,\"luan:Io\")" );
+		requireCall.add( "PackageLuan.require(luan,\"luan:Io\")" );
 		Expr stdoutExp = indexExpStr( requireCall.single(), constExpStr("stdout") );
 		Expr writeExp = indexExpStr( stdoutExp, constExpStr("write") );
 		Expr writeCall = callExpStr( writeExp, exprs );
 		Stmts stmt = new Stmts();
-		stmt.list.addAll( writeCall.list );
-		stmt.list.add( ";\n" );
+		stmt.addAll( writeCall );
+		stmt.add( ";\n" );
 		return stmt;
 	}
 
@@ -414,12 +414,12 @@
 			return parser.failure(null);
 		Expr exprs = ExpStringList(In.NOTHING);
 		Stmts stmt = new Stmts();
-		stmt.list.add( "return " );
+		stmt.add( "return " );
 		if( exprs != null )
-			stmt.list.addAll( exprs.list );
+			stmt.addAll( exprs );
 		else
-			stmt.list.add( "LuanFunction.NOTHING" );
-		stmt.list.add( ";\n" );
+			stmt.add( "LuanFunction.NOTHING" );
+		stmt.add( ";\n" );
 		return parser.success( stmt );
 	}
 
@@ -448,17 +448,9 @@
 			return parser.failure(null);
 		Stmts stmt = new Stmts();
 		String name = RequiredName(In.NOTHING);
-		stmt.list.addAll( addSymbol(name,null).list );
+		stmt.addAll( addSymbol(name,null) );
 		Expr fnDef = RequiredFunction(In.NOTHING);
-		stmt.list.addAll( nameVar(name).set(fnDef).list );
-/*
-		Settable s = new SetLocalVar(symbolsSize()-1);
-		Stmts stmt = new Stmts();
-		stmt.list.add( settableToString(s) );
-		stmt.list.add( ".set(luan," );
-		stmt.list.addAll( fnDef.list );
-		stmt.list.add( ");\n" );
-*/
+		stmt.addAll( nameVar(name).set(fnDef) );
 		return parser.success( stmt );
 	}
 
@@ -469,7 +461,7 @@
 		if( frame.loops <= 0 )
 			throw parser.exception("'break' outside of loop");
 		Stmts stmt = new Stmts();
-		stmt.list.add( "break;\n" );
+		stmt.add( "break;\n" );
 		return parser.success( stmt );
 	}
 
@@ -488,22 +480,22 @@
 
 		String fnVar = "fn"+ ++forCounter;
 		Expr fnExp = new Expr(null,false);
-		fnExp.list.add( fnVar + ".call(luan)" );
+		fnExp.add( fnVar + ".call(luan)" );
 		Stmts stmt = new Stmts();
-		stmt.list.add( ""
+		stmt.add( ""
 			+"LuanFunction "+fnVar+" = Luan.checkFunction("
 		);
-		stmt.list.addAll( expr.list );
-		stmt.list.add( ");\n" );
-		stmt.list.add( "while(true) {\n" );
-		stmt.list.addAll( makeLocalSetStmt(names,fnExp).list );
-		stmt.list.add( "if( " );
-		stmt.list.addAll( nameVar(names.get(0)).exp().list );
- 		stmt.list.add( "==null )  break;\n" );
+		stmt.addAll( expr );
+		stmt.add( ");\n" );
+		stmt.add( "while(true) {\n" );
+		stmt.addAll( makeLocalSetStmt(names,fnExp) );
+		stmt.add( "if( " );
+		stmt.addAll( nameVar(names.get(0)).exp() );
+ 		stmt.add( "==null )  break;\n" );
 		Stmts loop = RequiredLoopBlock();
 		RequiredKeyword("end",In.NOTHING);
-		stmt.list.addAll( loop.list );
-		stmt.list.add( "}\n" );
+		stmt.addAll( loop );
+		stmt.add( "}\n" );
 		popSymbols( symbolsSize() - stackStart );
 		return parser.success(stmt);
 	}
@@ -533,12 +525,12 @@
 			Expr values = ExpStringList(In.NOTHING);
 			if( values==null )
 				throw parser.exception("Expressions expected");
-			stmt.list.addAll( makeLocalSetStmt(names,values).list );
+			stmt.addAll( makeLocalSetStmt(names,values) );
 		} else {
 			Expr value = new Expr(Val.SINGLE,false);
-			value.list.add( "null" );
+			value.add( "null" );
 			for( String name : names ) {
-				stmt.list.addAll( addSymbol(name,value).list );
+				stmt.addAll( addSymbol(name,value) );
 			}
 		}
 		return parser.success(stmt);
@@ -584,11 +576,11 @@
 		Stmts loop = RequiredLoopBlock();
 		RequiredKeyword("end",In.NOTHING);
 		Stmts stmt = new Stmts();
-		stmt.list.add( "while( Luan.checkBoolean(" );
-		stmt.list.addAll( cnd.list );
-		stmt.list.add( ") ) {\n" );
-		stmt.list.addAll( loop.list );
-		stmt.list.add( "}\n" );
+		stmt.add( "while( Luan.checkBoolean(" );
+		stmt.addAll( cnd );
+		stmt.add( ") ) {\n" );
+		stmt.addAll( loop );
+		stmt.add( "}\n" );
 		return parser.success( stmt );
 	}
 
@@ -600,11 +592,11 @@
 		RequiredKeyword("until",In.NOTHING);
 		Expr cnd = RequiredExpr(In.NOTHING).single();
 		Stmts stmt = new Stmts();
-		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" );
+		stmt.add( "do {\n" );
+		stmt.addAll( loop );
+		stmt.add( "} while( !Luan.checkBoolean(" );
+		stmt.addAll( cnd );
+		stmt.add( ") );\n" );
 		return parser.success( stmt );
 	}
 
@@ -625,26 +617,26 @@
 		cnd = RequiredExpr(In.NOTHING).single();
 		RequiredKeyword("then",In.NOTHING);
 		block = RequiredBlock();
-		stmt.list.add( "if( Luan.checkBoolean(" );
-		stmt.list.addAll( cnd.list );
-		stmt.list.add( ") ) {\n" );
-		stmt.list.addAll( block.list );
+		stmt.add( "if( Luan.checkBoolean(" );
+		stmt.addAll( cnd );
+		stmt.add( ") ) {\n" );
+		stmt.addAll( block );
 		while( Keyword("elseif",In.NOTHING) ) {
 			cnd = RequiredExpr(In.NOTHING).single();
 			RequiredKeyword("then",In.NOTHING);
 			block = RequiredBlock();
-			stmt.list.add( "} else if( Luan.checkBoolean(" );
-			stmt.list.addAll( cnd.list );
-			stmt.list.add( ") ) {\n" );
-			stmt.list.addAll( block.list );
+			stmt.add( "} else if( Luan.checkBoolean(" );
+			stmt.addAll( cnd );
+			stmt.add( ") ) {\n" );
+			stmt.addAll( block );
 		}
 		if( Keyword("else",In.NOTHING) ) {
 			block = RequiredBlock();
-			stmt.list.add( "} else {\n" );
-			stmt.list.addAll( block.list );
+			stmt.add( "} else {\n" );
+			stmt.addAll( block );
 		}
 		RequiredKeyword("end",In.NOTHING);
-		stmt.list.add( "}\n" );
+		stmt.add( "}\n" );
 		return parser.success( stmt );
 	}
 
@@ -678,17 +670,17 @@
 			return vars.get(0).set(values);
 		Stmts stmt = new Stmts();
 		String varName = values.valType==Val.ARRAY ? "a" : "t";
-		stmt.list.add( varName + " = " );
-		stmt.list.addAll( values.list );
-		stmt.list.add( ";\n" );
+		stmt.add( varName + " = " );
+		stmt.addAll( values );
+		stmt.add( ";\n" );
 		Expr t = new Expr(values.valType,false);
-		t.list.add( varName );
+		t.add( varName );
 		t = t.single();
-		stmt.list.addAll( vars.get(0).set(t).list );
+		stmt.addAll( vars.get(0).set(t) );
 		for( int i=1; i<n; i++ ) {
-			t.list.clear();
-			t.list.add( "LuanImpl.pick(" + varName + ","+i+")" );
-			stmt.list.addAll( vars.get(i).set(t).list );
+			t.clear();
+			t.add( "LuanImpl.pick(" + varName + ","+i+")" );
+			stmt.addAll( vars.get(i).set(t) );
 		}
 		return stmt;
 	}
@@ -699,17 +691,17 @@
 			return addSymbol(names.get(0),values.single());
 		Stmts stmt = new Stmts();
 		String varName = values.valType==Val.ARRAY ? "a" : "t";
-		stmt.list.add( varName + " = " );
-		stmt.list.addAll( values.list );
-		stmt.list.add( ";\n" );
+		stmt.add( varName + " = " );
+		stmt.addAll( values );
+		stmt.add( ";\n" );
 		Expr t = new Expr(values.valType,false);
-		t.list.add( varName );
+		t.add( varName );
 		t = t.single();
-		stmt.list.addAll( addSymbol(names.get(0),t).list );
+		stmt.addAll( addSymbol(names.get(0),t) );
 		for( int i=1; i<n; i++ ) {
-			t.list.clear();
-			t.list.add( "LuanImpl.pick(" + varName + ","+i+")" );
-			stmt.list.addAll( addSymbol(names.get(i),t).list );
+			t.clear();
+			t.add( "LuanImpl.pick(" + varName + ","+i+")" );
+			stmt.addAll( addSymbol(names.get(i),t) );
 		}
 		return stmt;
 	}
@@ -720,13 +712,13 @@
 		if( exp != null && exp.isStmt ) {
 			Stmts stmt = new Stmts();
 			if( exp.valType==Val.SINGLE ) {
-				stmt.list.add( "LuanImpl.nop(" );
-				stmt.list.addAll( exp.list );
-				stmt.list.add( ")" );
+				stmt.add( "LuanImpl.nop(" );
+				stmt.addAll( exp );
+				stmt.add( ")" );
 			} else {
-				stmt.list.addAll( exp.list );
+				stmt.addAll( exp );
 			}
-			stmt.list.add( ";\n" );
+			stmt.add( ";\n" );
 			return parser.success( stmt );
 		}
 		return parser.failure(null);
@@ -758,11 +750,11 @@
 			exp = exp.single();
 			Expr exp2 = required(RelExpr(in)).single();
 			Expr newExp = new Expr(Val.SINGLE,true);
-			newExp.list.add( "(LuanImpl.cnd(t = " );
-			newExp.list.addAll( exp.list );
-			newExp.list.add( ") ? t : (" );
-			newExp.list.addAll( exp2.list );
-			newExp.list.add( "))" );
+			newExp.add( "(LuanImpl.cnd(t = " );
+			newExp.addAll( exp );
+			newExp.add( ") ? t : (" );
+			newExp.addAll( exp2 );
+			newExp.add( "))" );
 			exp = newExp;
 		}
 		return parser.success(exp);
@@ -777,11 +769,11 @@
 			exp = exp.single();
 			Expr exp2 = required(RelExpr(in)).single();
 			Expr newExp = new Expr(Val.SINGLE,true);
-			newExp.list.add( "(LuanImpl.cnd(t = " );
-			newExp.list.addAll( exp.list );
-			newExp.list.add( ") ? (" );
-			newExp.list.addAll( exp2.list );
-			newExp.list.add( ") : t)" );
+			newExp.add( "(LuanImpl.cnd(t = " );
+			newExp.addAll( exp );
+			newExp.add( ") ? (" );
+			newExp.addAll( exp2 );
+			newExp.add( ") : t)" );
 			exp = newExp;
 		}
 		return parser.success(exp);
@@ -798,66 +790,66 @@
 				exp = exp.single();
 				Expr exp2 = required(ConcatExpr(in)).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
-				newExp.list.add( "LuanImpl.eq(luan," );
-				newExp.list.addAll( exp.list );
-				newExp.list.add( "," );
-				newExp.list.addAll( exp2.list );
-				newExp.list.add( ")" );
+				newExp.add( "LuanImpl.eq(luan," );
+				newExp.addAll( exp );
+				newExp.add( "," );
+				newExp.addAll( exp2 );
+				newExp.add( ")" );
 				exp = newExp;
 			} else if( parser.match("~=") ) {
 				Spaces(in);
 				exp = exp.single();
 				Expr exp2 = required(ConcatExpr(in)).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
-				newExp.list.add( "!LuanImpl.eq(luan," );
-				newExp.list.addAll( exp.list );
-				newExp.list.add( "," );
-				newExp.list.addAll( exp2.list );
-				newExp.list.add( ")" );
+				newExp.add( "!LuanImpl.eq(luan," );
+				newExp.addAll( exp );
+				newExp.add( "," );
+				newExp.addAll( exp2 );
+				newExp.add( ")" );
 				exp = newExp;
 			} else if( parser.match("<=") ) {
 				Spaces(in);
 				exp = exp.single();
 				Expr exp2 = required(ConcatExpr(in)).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
-				newExp.list.add( "LuanImpl.le(luan," );
-				newExp.list.addAll( exp.list );
-				newExp.list.add( "," );
-				newExp.list.addAll( exp2.list );
-				newExp.list.add( ")" );
+				newExp.add( "LuanImpl.le(luan," );
+				newExp.addAll( exp );
+				newExp.add( "," );
+				newExp.addAll( exp2 );
+				newExp.add( ")" );
 				exp = newExp;
 			} else if( parser.match(">=") ) {
 				Spaces(in);
 				exp = exp.single();
 				Expr exp2 = required(ConcatExpr(in)).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
-				newExp.list.add( "LuanImpl.le(luan," );
-				newExp.list.addAll( exp2.list );
-				newExp.list.add( "," );
-				newExp.list.addAll( exp.list );
-				newExp.list.add( ")" );
+				newExp.add( "LuanImpl.le(luan," );
+				newExp.addAll( exp2 );
+				newExp.add( "," );
+				newExp.addAll( exp );
+				newExp.add( ")" );
 				exp = newExp;
 			} else if( parser.match("<") ) {
 				Spaces(in);
 				exp = exp.single();
 				Expr exp2 = required(ConcatExpr(in)).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
-				newExp.list.add( "LuanImpl.lt(luan," );
-				newExp.list.addAll( exp.list );
-				newExp.list.add( "," );
-				newExp.list.addAll( exp2.list );
-				newExp.list.add( ")" );
+				newExp.add( "LuanImpl.lt(luan," );
+				newExp.addAll( exp );
+				newExp.add( "," );
+				newExp.addAll( exp2 );
+				newExp.add( ")" );
 				exp = newExp;
 			} else if( parser.match(">") ) {
 				Spaces(in);
 				exp = exp.single();
 				Expr exp2 = required(ConcatExpr(in)).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
-				newExp.list.add( "LuanImpl.lt(luan," );
-				newExp.list.addAll( exp2.list );
-				newExp.list.add( "," );
-				newExp.list.addAll( exp.list );
-				newExp.list.add( ")" );
+				newExp.add( "LuanImpl.lt(luan," );
+				newExp.addAll( exp2 );
+				newExp.add( "," );
+				newExp.addAll( exp );
+				newExp.add( ")" );
 				exp = newExp;
 			} else
 				break;
@@ -875,11 +867,11 @@
 			exp = exp.single();
 			Expr exp2 = required(ConcatExpr(in)).single();
 			Expr newExp = new Expr(Val.SINGLE,false);
-			newExp.list.add( "LuanImpl.concat(luan," );
-			newExp.list.addAll( exp.list );
-			newExp.list.add( "," );
-			newExp.list.addAll( exp2.list );
-			newExp.list.add( ")" );
+			newExp.add( "LuanImpl.concat(luan," );
+			newExp.addAll( exp );
+			newExp.add( "," );
+			newExp.addAll( exp2 );
+			newExp.add( ")" );
 			exp = newExp;
 		}
 		return parser.success(exp);
@@ -896,22 +888,22 @@
 				exp = exp.single();
 				Expr exp2 = required(TermExpr(in)).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
-				newExp.list.add( "LuanImpl.add(luan," );
-				newExp.list.addAll( exp.list );
-				newExp.list.add( "," );
-				newExp.list.addAll( exp2.list );
-				newExp.list.add( ")" );
+				newExp.add( "LuanImpl.add(luan," );
+				newExp.addAll( exp );
+				newExp.add( "," );
+				newExp.addAll( exp2 );
+				newExp.add( ")" );
 				exp = newExp;
 			} else if( Minus() ) {
 				Spaces(in);
 				exp = exp.single();
 				Expr exp2 = required(TermExpr(in)).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
-				newExp.list.add( "LuanImpl.sub(luan," );
-				newExp.list.addAll( exp.list );
-				newExp.list.add( "," );
-				newExp.list.addAll( exp2.list );
-				newExp.list.add( ")" );
+				newExp.add( "LuanImpl.sub(luan," );
+				newExp.addAll( exp );
+				newExp.add( "," );
+				newExp.addAll( exp2 );
+				newExp.add( ")" );
 				exp = newExp;
 			} else
 				break;
@@ -935,33 +927,33 @@
 				exp = exp.single();
 				Expr exp2 = required(UnaryExpr(in)).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
-				newExp.list.add( "LuanImpl.mul(luan," );
-				newExp.list.addAll( exp.list );
-				newExp.list.add( "," );
-				newExp.list.addAll( exp2.list );
-				newExp.list.add( ")" );
+				newExp.add( "LuanImpl.mul(luan," );
+				newExp.addAll( exp );
+				newExp.add( "," );
+				newExp.addAll( exp2 );
+				newExp.add( ")" );
 				exp = newExp;
 			} else if( parser.match('/') ) {
 				Spaces(in);
 				exp = exp.single();
 				Expr exp2 = required(UnaryExpr(in)).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
-				newExp.list.add( "LuanImpl.div(luan," );
-				newExp.list.addAll( exp.list );
-				newExp.list.add( "," );
-				newExp.list.addAll( exp2.list );
-				newExp.list.add( ")" );
+				newExp.add( "LuanImpl.div(luan," );
+				newExp.addAll( exp );
+				newExp.add( "," );
+				newExp.addAll( exp2 );
+				newExp.add( ")" );
 				exp = newExp;
 			} else if( Mod() ) {
 				Spaces(in);
 				exp = exp.single();
 				Expr exp2 = required(UnaryExpr(in)).single();
 				Expr newExp = new Expr(Val.SINGLE,false);
-				newExp.list.add( "LuanImpl.mod(luan," );
-				newExp.list.addAll( exp.list );
-				newExp.list.add( "," );
-				newExp.list.addAll( exp2.list );
-				newExp.list.add( ")" );
+				newExp.add( "LuanImpl.mod(luan," );
+				newExp.addAll( exp );
+				newExp.add( "," );
+				newExp.addAll( exp2 );
+				newExp.add( ")" );
 				exp = newExp;
 			} else
 				break;
@@ -980,27 +972,27 @@
 			Spaces(in);
 			Expr exp = required(UnaryExpr(in)).single();
 			Expr newExp = new Expr(Val.SINGLE,false);
-			newExp.list.add( "LuanImpl.len(luan," );
-			newExp.list.addAll( exp.list );
-			newExp.list.add( ")" );
+			newExp.add( "LuanImpl.len(luan," );
+			newExp.addAll( exp );
+			newExp.add( ")" );
 			return parser.success(newExp);
 		}
 		if( Minus() ) {
 			Spaces(in);
 			Expr exp = required(UnaryExpr(in)).single();
 			Expr newExp = new Expr(Val.SINGLE,false);
-			newExp.list.add( "LuanImpl.unm(luan," );
-			newExp.list.addAll( exp.list );
-			newExp.list.add( ")" );
+			newExp.add( "LuanImpl.unm(luan," );
+			newExp.addAll( exp );
+			newExp.add( ")" );
 			return parser.success(newExp);
 		}
 		if( Keyword("not",in) ) {
 			Spaces(in);
 			Expr exp = required(UnaryExpr(in)).single();
 			Expr newExp = new Expr(Val.SINGLE,false);
-			newExp.list.add( "!Luan.checkBoolean(" );
-			newExp.list.addAll( exp.list );
-			newExp.list.add( ")" );
+			newExp.add( "!Luan.checkBoolean(" );
+			newExp.addAll( exp );
+			newExp.add( ")" );
 			return parser.success(newExp);
 		}
 		Expr exp = PowExpr(in);
@@ -1018,11 +1010,11 @@
 			Spaces(in);
 			Expr exp2 = required(PowExpr(in));
 			Expr newExp = new Expr(Val.SINGLE,false);
-			newExp.list.add( "LuanImpl.pow(luan," );
-			newExp.list.addAll( exp1.single().list );
-			newExp.list.add( "," );
-			newExp.list.addAll( exp2.single().list );
-			newExp.list.add( ")" );
+			newExp.add( "LuanImpl.pow(luan," );
+			newExp.addAll( exp1.single() );
+			newExp.add( "," );
+			newExp.addAll( exp2.single() );
+			newExp.add( ")" );
 			exp1 = newExp;
 		}
 		return parser.success(exp1);
@@ -1058,25 +1050,25 @@
 		List<String> names = NameList(in);
 		if( names != null ) {
 			Expr args = new Expr(Val.ARRAY,false);
-			args.list.add( "args" );
-			stmt.list.addAll( makeLocalSetStmt(names,args).list );
+			args.add( "args" );
+			stmt.addAll( makeLocalSetStmt(names,args) );
 			if( parser.match(',') ) {
 				Spaces(inParens);
 				if( !parser.match("...") )
 					throw parser.exception();
 				Spaces(inParens);
 				frame.isVarArg = true;
-				stmt.list.add( "final Object[] varArgs = LuanImpl.varArgs(args," + names.size() + ");\n" );
+				stmt.add( "final Object[] varArgs = LuanImpl.varArgs(args," + names.size() + ");\n" );
 			}
 		} else if( parser.match("...") ) {
 			Spaces(inParens);
 			frame.isVarArg = true;
-			stmt.list.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" );
+			stmt.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" );
 		}
 		RequiredMatch(')');
 		Spaces(in);
 		Stmts block = RequiredBlock();
-		stmt.list.addAll( block.list );
+		stmt.addAll( block );
 		stmt.hasReturn = block.hasReturn;
 		RequiredKeyword("end",in);
 		Expr fnDef = newFnExpStr(start,stmt);
@@ -1090,7 +1082,7 @@
 			return parser.failure(null);
 		Spaces(in);
 		Expr exp = new Expr(Val.ARRAY,false);
-		exp.list.add("varArgs");
+		exp.add("varArgs");
 		return parser.success(exp);
 	}
 
@@ -1112,9 +1104,9 @@
 			throw parser.exception("Expected table element or '}'");
 		Spaces(in);
 		exp = new Expr(Val.SINGLE,false);
-		exp.list.add( "LuanImpl.table(" );
-		exp.list.addAll( expString(builder).array().list );
-		exp.list.add( ")" );
+		exp.add( "LuanImpl.table(" );
+		exp.addAll( expString(builder).array() );
+		exp.add( ")" );
 		return parser.success( exp );
 	}
 
@@ -1131,11 +1123,11 @@
 			Spaces(In.NOTHING);
 			Expr val = RequiredExpr(In.NOTHING).single();
 			Expr newExp = new Expr(Val.SINGLE,false);
-			newExp.list.add( "new TableField(" );
-			newExp.list.addAll( exp.list );
-			newExp.list.add( "," );
-			newExp.list.addAll( val.list );
-			newExp.list.add( ")" );
+			newExp.add( "new TableField(" );
+			newExp.addAll( exp );
+			newExp.add( "," );
+			newExp.addAll( val );
+			newExp.add( ")" );
 			builder.add( newExp );
 			return parser.success();
 		}
@@ -1241,10 +1233,10 @@
 				Sym sym = getSym(name);
 				if( sym != null ) {
 					Stmts stmt = new Stmts();
-					stmt.list.addAll( sym.exp().list );
-					stmt.list.add( " = " );
-					stmt.list.addAll( val.single().list );
-					stmt.list.add( ";\n" );
+					stmt.addAll( sym.exp() );
+					stmt.add( " = " );
+					stmt.addAll( val.single() );
+					stmt.add( ";\n" );
 					return stmt;
 				}
 				Expr envExpr = env();
@@ -1285,13 +1277,13 @@
 
 			public Stmts set(Expr val) {
 				Stmts stmt = new Stmts();
-				stmt.list.add( "LuanImpl.put(luan," );
-				stmt.list.addAll( table.single().list );
-				stmt.list.add( "," );
-				stmt.list.addAll( key.single().list );
-				stmt.list.add( "," );
-				stmt.list.addAll( val.single().list );
-				stmt.list.add( ");\n" );
+				stmt.add( "LuanImpl.put(luan," );
+				stmt.addAll( table.single() );
+				stmt.add( "," );
+				stmt.addAll( key.single() );
+				stmt.add( "," );
+				stmt.addAll( val.single() );
+				stmt.add( ");\n" );
 				return stmt;
 			}
 		};
@@ -1462,13 +1454,13 @@
 		parser.begin();
 		if( NilLiteral(in) ) {
 			Expr exp = new Expr(Val.SINGLE,false);
-			exp.list.add( "null" );
+			exp.add( "null" );
 			return parser.success(exp);
 		}
 		Boolean b = BooleanLiteral(in);
 		if( b != null ) {
 			Expr exp = new Expr(Val.SINGLE,false);
-			exp.list.add( b.toString() );
+			exp.add( b.toString() );
 			return parser.success(exp);
 		}
 		Number n = NumberLiteral(in);
@@ -1477,7 +1469,7 @@
 			if( n instanceof Long )
 				s += "L";
 			Expr exp = new Expr(Val.SINGLE,false);
-			exp.list.add( s );
+			exp.add( s );
 			return parser.success(exp);
 		}
 		String s = StringLiteral(in);
@@ -1496,7 +1488,7 @@
 			.replace("\b","\\b")
 		;
 		Expr exp = new Expr(Val.SINGLE,false);
-		exp.list.add( "\""+s+"\"" );
+		exp.add( "\""+s+"\"" );
 		return exp;
 	}
 
@@ -1746,13 +1738,33 @@
 
 
 
+	private static class ParseList extends ArrayList {
+
+		@Override public boolean add(Object obj) {
+			if( obj instanceof List )  throw new RuntimeException();
+			return super.add(obj);
+		}
+
+		@Override public void add(int index,Object obj) {
+			if( obj instanceof List )  throw new RuntimeException();
+			super.add(index,obj);
+		}
+
+		@Override public String toString() {
+			StringBuilder sb = new StringBuilder();
+			for( Object o : this ) {
+				sb.append( o.toString() );
+			}
+			return sb.toString();
+		}
+	}
+
 
 	private static AtomicInteger classCounter = new AtomicInteger();
 
 	private enum Val { SINGLE, ARRAY }
 
-	private class Expr {
-		final List list = new ArrayList();
+	private static class Expr extends ParseList {
 		final Val valType;
 		final boolean isStmt;
 
@@ -1765,9 +1777,9 @@
 			if( valType==Val.SINGLE )
 				return this;
 			Expr exp = new Expr(Val.SINGLE,isStmt);
-			exp.list.add( valType==Val.ARRAY ? "LuanImpl.first(" : "Luan.first(" );
-			exp.list.addAll( list );
-			exp.list.add( ")" );
+			exp.add( valType==Val.ARRAY ? "LuanImpl.first(" : "Luan.first(" );
+			exp.addAll( this );
+			exp.add( ")" );
 			return exp;
 		}
 
@@ -1776,13 +1788,13 @@
 				return this;
 			Expr exp = new Expr(Val.ARRAY,isStmt);
 			if( valType==Val.SINGLE ) {
-				exp.list.add( "new Object[]{" );
-				exp.list.addAll( list );
-				exp.list.add( "}" );
+				exp.add( "new Object[]{" );
+				exp.addAll( this );
+				exp.add( "}" );
 			} else {
-				exp.list.add( "Luan.array(" );
-				exp.list.addAll( list );
-				exp.list.add( ")" );
+				exp.add( "Luan.array(" );
+				exp.addAll( this );
+				exp.add( ")" );
 			}
 			return exp;
 		}
@@ -1793,52 +1805,37 @@
 		Expr exp = new Expr(Val.ARRAY,false);
 		switch(list.size()) {
 		case 0:
-			exp.list.add("LuanFunction.NOTHING");
+			exp.add("LuanFunction.NOTHING");
 			return exp;
 		case 1:
 			return list.get(0);
 		default:
 			int lastI = list.size() - 1;
-			exp.list.add( "new Object[]{" );
+			exp.add( "new Object[]{" );
 			for( int i=0; i<lastI; i++ ) {
-				exp.list.addAll( list.get(i).single().list );
-				exp.list.add( "," );
+				exp.addAll( list.get(i).single() );
+				exp.add( "," );
 			}
 			Expr last = list.get(lastI);
 			if( last.valType==Val.SINGLE ) {
-				exp.list.addAll( last.list );
-				exp.list.add( "}" );
+				exp.addAll( last );
+				exp.add( "}" );
 			} else {
-				exp.list.add( "}" );
-				exp.list.add( 0, "LuanImpl.concatArgs(" );
-				exp.list.add( "," );
-				exp.list.addAll( last.list );
-				exp.list.add( ")" );
+				exp.add( "}" );
+				exp.add( 0, "LuanImpl.concatArgs(" );
+				exp.add( "," );
+				exp.addAll( last );
+				exp.add( ")" );
 			}
 			return exp;
 		}
 	}
 
-	private static class Stmts {
-		final List list = new ArrayList();
+	private static class Stmts extends ParseList {
 		boolean hasReturn = false;
 	}
 
-	private static String concat(List list) {
-		StringBuilder sb = new StringBuilder();
-		for( Object o : list ) {
-			if( o instanceof List )  throw new RuntimeException();
-			if( o instanceof Expr )  throw new RuntimeException();
-			if( o instanceof Stmts )  throw new RuntimeException();
-			sb.append( o.toString() );
-		}
-		return sb.toString();
-	}
-
-	private Class toFnClass(Stmts stmt,List<UpSym> upValueSymbols) {
-		String code = concat(stmt.list);
-//System.out.println("code:\n"+code);
-
+	private Class toFnClass(Stmts stmts,List<UpSym> upValueSymbols) {
 		String className = "EXP" + classCounter.incrementAndGet();
 		String classCode = ""
 			+"package luan.impl;\n"
@@ -1858,7 +1855,7 @@
 			+"	@Override public Object doCall(LuanState luan,Object[] args) throws LuanException {\n"
 			+"		Object t;\n"
 			+"		Object[] a;\n"
-			+"		" + code
+			+"		" + stmts
 			+"	}\n"
 			+"}\n"
 		;
@@ -1871,9 +1868,9 @@
 		}
 	}
 
-	private Expr toFnExpStr(Stmts stmt,List<UpSym> upValueSymbols) {
+	private static Expr toFnExpStr(Stmts stmt,List<UpSym> upValueSymbols) {
 		Expr exp = new Expr(Val.SINGLE,false);
-		exp.list.add( ""
+		exp.add( ""
 			+"\n"
 			+"new Closure("+upValueSymbols.size()+",java) {\n"
 			+"{\n"
@@ -1884,8 +1881,8 @@
 			+"		Object[] a;\n"
 			+"		"
 		);
-		exp.list.addAll( stmt.list );
-		exp.list.add( ""
+		exp.addAll( stmt );
+		exp.add( ""
 			+"	}\n"
 			+"}\n"
 		);