changeset 674:2994e46f62b7

some optimization
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 12 Apr 2016 19:31:18 -0600
parents 33629d753cf9
children d95caff8ba8c
files core/src/luan/impl/LuanImpl.java core/src/luan/impl/LuanParser.java
diffstat 2 files changed, 285 insertions(+), 313 deletions(-) [+]
line wrap: on
line diff
--- a/core/src/luan/impl/LuanImpl.java	Tue Apr 12 17:09:06 2016 -0600
+++ b/core/src/luan/impl/LuanImpl.java	Tue Apr 12 19:31:18 2016 -0600
@@ -14,20 +14,6 @@
 public final class LuanImpl {
 	private LuanImpl() {}  // never
 
-/*
-	private static List list = new ArrayList();
-
-	static int addObj(Object obj) {
-		int i = list.size();
-		list.add(obj);
-		return i;
-	}
-
-	public static Object getObj(int i) {
-		return list.get(i);
-	}
-*/
-
 	public static int len(LuanState luan,Object o) throws LuanException {
 		if( o instanceof String ) {
 			String s = (String)o;
@@ -191,10 +177,7 @@
 		return i<a.length ? a[i] : null;
 	}
 
-	public static Object[] varArgs(Object o,int i) {
-		if( !(o instanceof Object[]) )
-			return i==0 ? new Object[]{o} : LuanFunction.NOTHING;
-		Object[] a = (Object[])o;
+	public static Object[] varArgs(Object[] a,int i) {
 		if( i >= a.length )
 			return LuanFunction.NOTHING;
 		Object[] rtn = new Object[a.length - i];
@@ -233,10 +216,10 @@
 		}
 	}
 
-	public static LuanTable table(Object o) {
+	public static LuanTable table(Object[] a) {
 		LuanTable table = new LuanTable();
 		int i = 0;
-		for( Object fld : Luan.array(o) ) {
+		for( Object fld : a ) {
 			if( fld instanceof TableField ) {
 				TableField tblFld = (TableField)fld;
 				Object key = tblFld.key;
@@ -252,4 +235,8 @@
 		return table;
 	}
 
+	public static Object first(Object[] a) {
+		return a.length==0 ? null : a[0];
+	}
+
 }
--- a/core/src/luan/impl/LuanParser.java	Tue Apr 12 17:09:06 2016 -0600
+++ b/core/src/luan/impl/LuanParser.java	Tue Apr 12 19:31:18 2016 -0600
@@ -14,7 +14,7 @@
 final class LuanParser {
 
 	private interface Sym {
-		public ExpString exp();
+		public Expr exp();
 	}
 
 	private int symCounter = 0;
@@ -29,8 +29,8 @@
 			this.javaName = name + "_" + (++symCounter);
 		}
 
-		StmtString declaration(ExpString value) {
-			StmtString stmt = new StmtString();
+		Stmts declaration(Expr value) {
+			Stmts stmt = new Stmts();
 			if( value==null ) {
 				stmt.list.add( new Object() {
 					@Override public String toString() {
@@ -41,6 +41,7 @@
 					}
 				} );
 			} else {
+				if( value.valType != Val.SINGLE )  throw new RuntimeException();
 				stmt.list.add( new Object() {
 					@Override public String toString() {
 						if( !isPointer )
@@ -62,8 +63,8 @@
 			return stmt;
 		}
 
-		@Override public ExpString exp() {
-			ExpString exp = new ExpString(true,false);
+		@Override public Expr exp() {
+			Expr exp = new Expr(Val.SINGLE,false);
 			exp.list.add( new Object() {
 				@Override public String toString() {
 					if( !isPointer )
@@ -91,8 +92,8 @@
 			return "upValues[" + i + "] = " + value + ";\n";
 		}
 
-		@Override public ExpString exp() {
-			ExpString exp = new ExpString(true,false);
+		@Override public Expr exp() {
+			Expr exp = new Expr(Val.SINGLE,false);
 			exp.list.add( new Object() {
 				@Override public String toString() {
 					return "upValues[" + i + "].o";
@@ -184,7 +185,7 @@
 //	final LuanSource source;
 	private Frame frame;
 	private final Parser parser;
-	private final StmtString top = new StmtString();
+	private final Stmts top = new Stmts();
 
 	LuanParser(String sourceName,String sourceText) {
 //		this.source = source;
@@ -205,7 +206,7 @@
 		return frame.symbols.size();
 	}
 
-	private StmtString addSymbol(String name,ExpString value) {
+	private Stmts addSymbol(String name,Expr value) {
 		final LocalSym sym = frame.addLocalSym(name);
 		return sym.declaration(value);
 	}
@@ -240,22 +241,14 @@
 			throw parser.exception(msg);
 		return t;
 	}
-/*
-	private static Expr expr(Expressions exprs) {
-		if( exprs==null )
-			return null;
-		if( exprs instanceof Expr )
-			return (Expr)exprs; 
-		return new ExpressionsExpr(exprs);
-	}
-*/
-	private Class newFnClass(int start,StmtString stmt) {
+
+	private Class newFnClass(int start,Stmts stmt) {
 		if( !stmt.hasReturn )
 			stmt.list.add( "return LuanFunction.NOTHING;\n" );
 		return toFnClass( stmt, frame.upValueSymbols );
 	}
 
-	private ExpString newFnExpStr(int start,StmtString stmt) {
+	private Expr newFnExpStr(int start,Stmts stmt) {
 		if( !stmt.hasReturn )
 			stmt.list.add( "return LuanFunction.NOTHING;\n" );
 		return toFnExpStr( stmt, frame.upValueSymbols );
@@ -264,7 +257,7 @@
 	Class Expression() throws ParseException {
 		Spaces(In.NOTHING);
 		int start = parser.begin();
-		ExpString expr = ExprZ(In.NOTHING);
+		Expr expr = ExprZ(In.NOTHING);
 		if( expr != null && parser.endOfInput() ) {
 			top.list.add( "return " );
 			top.list.addAll( expr.list );
@@ -280,7 +273,7 @@
 		int start = parser.begin();
 		frame.isVarArg = true;
 		top.list.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" );
-		StmtString block = RequiredBlock();
+		Stmts block = RequiredBlock();
 		top.list.addAll( block.list );
 		top.hasReturn = block.hasReturn;
 		if( parser.endOfInput() )
@@ -288,8 +281,8 @@
 		throw parser.exception();
 	}
 
-	private StmtString RequiredBlock() throws ParseException {
-		StmtString stmts = new StmtString();
+	private Stmts RequiredBlock() throws ParseException {
+		Stmts stmts = new Stmts();
 		int stackStart = symbolsSize();
 		boolean isReturn = Stmt(stmts);
 		while( !isReturn && StmtSep(stmts) ) {
@@ -304,7 +297,7 @@
 		return stmts;
 	}
 
-	private boolean StmtSep(StmtString stmts) throws ParseException {
+	private boolean StmtSep(Stmts stmts) throws ParseException {
 		parser.begin();
 		if( parser.match( ';' ) )
 			return parser.success();
@@ -312,7 +305,7 @@
 			return parser.success();
 		if( stmts != null ) {
 //			parser.rollback();
-			StmtString stmt = TemplateStmt();
+			Stmts stmt = TemplateStmt();
 			if( stmt != null ) {
 				stmts.list.addAll(stmt.list);
 				return parser.success();
@@ -325,8 +318,8 @@
 		return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' );
 	}
 
-	private boolean Stmt(StmtString stmts) throws ParseException {
-		StmtString stmt;
+	private boolean Stmt(Stmts stmts) throws ParseException {
+		Stmts stmt;
 		if( (stmt=ReturnStmt()) != null ) {
 			stmts.list.addAll(stmt.list);
 			return true;
@@ -348,42 +341,42 @@
 		return false;
 	}
 
-	private ExpString indexExpStr(ExpString exp1,ExpString exp2) {
-		ExpString exp = new ExpString(true,false);
+	private Expr indexExpStr(Expr exp1,Expr exp2) {
+		Expr exp = new Expr(Val.SINGLE,false);
 		exp.list.add( "luan.index(" );
-		exp.list.addAll( exp1.expr().list );
+		exp.list.addAll( exp1.single().list );
 		exp.list.add( "," );
-		exp.list.addAll( exp2.expr().list );
+		exp.list.addAll( exp2.single().list );
 		exp.list.add( ")" );
 		return exp;
 	}
 
-	private ExpString callExpStr(ExpString fn,ExpString args) {
-		ExpString exp = new ExpString(false,true);
+	private Expr callExpStr(Expr fn,Expr args) {
+		Expr exp = new Expr(null,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( "))" );
+		exp.list.addAll( fn.single().list );
+		exp.list.add( ").call(luan," );
+		exp.list.addAll( args.array().list );
+		exp.list.add( ")" );
 		return exp;
 	}
 
-	private StmtString TemplateStmt() throws ParseException {
-		ExpString exprs = TemplateExpressions(In.NOTHING);
+	private Stmts TemplateStmt() throws ParseException {
+		Expr exprs = TemplateExpressions(In.NOTHING);
 		if( exprs == null )
 			return null;
-		ExpString requireCall = new ExpString(true,false);
+		Expr requireCall = new Expr(Val.SINGLE,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 );
-		StmtString stmt = new StmtString();
+		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" );
 		return stmt;
 	}
 
-	private ExpString TemplateExpressions(In in) throws ParseException {
+	private Expr TemplateExpressions(In in) throws ParseException {
 		if( in.template )
 			return null;
 		int start = parser.begin();
@@ -391,7 +384,7 @@
 			return parser.failure(null);
 		EndOfLine();
 		In inTemplate = in.template();
-		List<ExpString> builder = new ArrayList<ExpString>();
+		List<Expr> builder = new ArrayList<Expr>();
 		while(true) {
 			if( parser.match( "<%=" ) ) {
 				Spaces(inTemplate);
@@ -414,12 +407,12 @@
 		}
 	}
 
-	private StmtString ReturnStmt() throws ParseException {
+	private Stmts ReturnStmt() throws ParseException {
 		parser.begin();
 		if( !Keyword("return",In.NOTHING) )
 			return parser.failure(null);
-		ExpString exprs = ExpStringList(In.NOTHING);
-		StmtString stmt = new StmtString();
+		Expr exprs = ExpStringList(In.NOTHING);
+		Stmts stmt = new Stmts();
 		stmt.list.add( "return " );
 		if( exprs != null )
 			stmt.list.addAll( exprs.list );
@@ -429,7 +422,7 @@
 		return parser.success( stmt );
 	}
 
-	private StmtString FunctionStmt() throws ParseException {
+	private Stmts FunctionStmt() throws ParseException {
 		parser.begin();
 		if( !Keyword("function",In.NOTHING) )
 			return parser.failure(null);
@@ -438,28 +431,28 @@
 		Var var = nameVar(RequiredName(In.NOTHING));
 		while( parser.match( '.' ) ) {
 			Spaces(In.NOTHING);
-			ExpString exp = NameExpr(In.NOTHING);
+			Expr exp = NameExpr(In.NOTHING);
 			if( exp==null )
 				return parser.failure(null);
 			var = indexVar( var.exp(), exp );
 		}
 
-		ExpString fnDef = RequiredFunction(In.NOTHING);
+		Expr fnDef = RequiredFunction(In.NOTHING);
 		return parser.success( var.set(fnDef) );
 	}
 
-	private StmtString LocalFunctionStmt() throws ParseException {
+	private Stmts LocalFunctionStmt() throws ParseException {
 		parser.begin();
 		if( !(Keyword("local",In.NOTHING) && Keyword("function",In.NOTHING)) )
 			return parser.failure(null);
-		StmtString stmt = new StmtString();
+		Stmts stmt = new Stmts();
 		String name = RequiredName(In.NOTHING);
 		stmt.list.addAll( addSymbol(name,null).list );
-		ExpString fnDef = RequiredFunction(In.NOTHING);
+		Expr fnDef = RequiredFunction(In.NOTHING);
 		stmt.list.addAll( nameVar(name).set(fnDef).list );
 /*
 		Settable s = new SetLocalVar(symbolsSize()-1);
-		StmtString stmt = new StmtString();
+		Stmts stmt = new Stmts();
 		stmt.list.add( settableToString(s) );
 		stmt.list.add( ".set(luan," );
 		stmt.list.addAll( fnDef.list );
@@ -468,20 +461,20 @@
 		return parser.success( stmt );
 	}
 
-	private StmtString BreakStmt() throws ParseException {
+	private Stmts 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");
-		StmtString stmt = new StmtString();
+		Stmts stmt = new Stmts();
 		stmt.list.add( "break;\n" );
 		return parser.success( stmt );
 	}
 
 	int forCounter = 0;
 
-	private StmtString ForStmt() throws ParseException {
+	private Stmts ForStmt() throws ParseException {
 		parser.begin();
 		int stackStart = symbolsSize();
 		if( !Keyword("for",In.NOTHING) )
@@ -489,13 +482,13 @@
 		List<String> names = RequiredNameList(In.NOTHING);
 		if( !Keyword("in",In.NOTHING) )
 			return parser.failure(null);
-		ExpString expr = RequiredExpr(In.NOTHING).expr();
+		Expr expr = RequiredExpr(In.NOTHING).single();
 		RequiredKeyword("do",In.NOTHING);
 
 		String fnVar = "fn"+ ++forCounter;
-		ExpString fnExp = new ExpString(false,false);
+		Expr fnExp = new Expr(null,false);
 		fnExp.list.add( fnVar + ".call(luan)" );
-		StmtString stmt = new StmtString();
+		Stmts stmt = new Stmts();
 		stmt.list.add( ""
 			+"LuanFunction "+fnVar+" = Luan.checkFunction("
 		);
@@ -506,7 +499,7 @@
 		stmt.list.add( "if( " );
 		stmt.list.addAll( nameVar(names.get(0)).exp().list );
  		stmt.list.add( "==null )  break;\n" );
-		StmtString loop = RequiredLoopBlock();
+		Stmts loop = RequiredLoopBlock();
 		RequiredKeyword("end",In.NOTHING);
 		stmt.list.addAll( loop.list );
 		stmt.list.add( "}\n" );
@@ -514,16 +507,16 @@
 		return parser.success(stmt);
 	}
 
-	private StmtString DoStmt() throws ParseException {
+	private Stmts DoStmt() throws ParseException {
 		parser.begin();
 		if( !Keyword("do",In.NOTHING) )
 			return parser.failure(null);
-		StmtString stmt = RequiredBlock();
+		Stmts stmt = RequiredBlock();
 		RequiredKeyword("end",In.NOTHING);
 		return parser.success(stmt);
 	}
 
-	private StmtString LocalStmt() throws ParseException {
+	private Stmts LocalStmt() throws ParseException {
 		parser.begin();
 		if( !Keyword("local",In.NOTHING) )
 			return parser.failure(null);
@@ -533,15 +526,15 @@
 				return parser.failure(null);  // handled later
 			throw parser.exception("Invalid local statement");
 		}
-		StmtString stmt = new StmtString();
+		Stmts stmt = new Stmts();
 		if( parser.match( '=' ) ) {
 			Spaces(In.NOTHING);
-			ExpString values = ExpStringList(In.NOTHING);
+			Expr values = ExpStringList(In.NOTHING);
 			if( values==null )
 				throw parser.exception("Expressions expected");
 			stmt.list.addAll( makeLocalSetStmt(names,values).list );
 		} else {
-			ExpString value = new ExpString(true,false);
+			Expr value = new Expr(Val.SINGLE,false);
 			value.list.add( "null" );
 			for( String name : names ) {
 				stmt.list.addAll( addSymbol(name,value).list );
@@ -581,15 +574,15 @@
 		return parser.success(name);
 	}
 
-	private StmtString WhileStmt() throws ParseException {
+	private Stmts WhileStmt() throws ParseException {
 		parser.begin();
 		if( !Keyword("while",In.NOTHING) )
 			return parser.failure(null);
-		ExpString cnd = RequiredExpr(In.NOTHING).expr();
+		Expr cnd = RequiredExpr(In.NOTHING).single();
 		RequiredKeyword("do",In.NOTHING);
-		StmtString loop = RequiredLoopBlock();
+		Stmts loop = RequiredLoopBlock();
 		RequiredKeyword("end",In.NOTHING);
-		StmtString stmt = new StmtString();
+		Stmts stmt = new Stmts();
 		stmt.list.add( "while( Luan.checkBoolean(" );
 		stmt.list.addAll( cnd.list );
 		stmt.list.add( ") ) {\n" );
@@ -598,14 +591,14 @@
 		return parser.success( stmt );
 	}
 
-	private StmtString RepeatStmt() throws ParseException {
+	private Stmts RepeatStmt() throws ParseException {
 		parser.begin();
 		if( !Keyword("repeat",In.NOTHING) )
 			return parser.failure(null);
-		StmtString loop =RequiredLoopBlock();
+		Stmts loop =RequiredLoopBlock();
 		RequiredKeyword("until",In.NOTHING);
-		ExpString cnd = RequiredExpr(In.NOTHING).expr();
-		StmtString stmt = new StmtString();
+		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(" );
@@ -614,21 +607,21 @@
 		return parser.success( stmt );
 	}
 
-	private StmtString RequiredLoopBlock() throws ParseException {
+	private Stmts RequiredLoopBlock() throws ParseException {
 		incLoops();
-		StmtString stmt = RequiredBlock();
+		Stmts stmt = RequiredBlock();
 		decLoops();
 		return stmt;
 	}
 
-	private StmtString IfStmt() throws ParseException {
+	private Stmts IfStmt() throws ParseException {
 		parser.begin();
 		if( !Keyword("if",In.NOTHING) )
 			return parser.failure(null);
-		StmtString stmt = new StmtString();
-		ExpString cnd;
-		StmtString block;
-		cnd = RequiredExpr(In.NOTHING).expr();
+		Stmts stmt = new Stmts();
+		Expr cnd;
+		Stmts block;
+		cnd = RequiredExpr(In.NOTHING).single();
 		RequiredKeyword("then",In.NOTHING);
 		block = RequiredBlock();
 		stmt.list.add( "if( Luan.checkBoolean(" );
@@ -636,7 +629,7 @@
 		stmt.list.add( ") ) {\n" );
 		stmt.list.addAll( block.list );
 		while( Keyword("elseif",In.NOTHING) ) {
-			cnd = RequiredExpr(In.NOTHING).expr();
+			cnd = RequiredExpr(In.NOTHING).single();
 			RequiredKeyword("then",In.NOTHING);
 			block = RequiredBlock();
 			stmt.list.add( "} else if( Luan.checkBoolean(" );
@@ -654,7 +647,7 @@
 		return parser.success( stmt );
 	}
 
-	private StmtString SetStmt() throws ParseException {
+	private Stmts SetStmt() throws ParseException {
 		parser.begin();
 		List<Var> vars = new ArrayList<Var>();
 		Var v = SettableVar();
@@ -671,57 +664,61 @@
 		if( !parser.match( '=' ) )
 			return parser.failure(null);
 		Spaces(In.NOTHING);
-		ExpString values = ExpStringList(In.NOTHING);
+		Expr values = ExpStringList(In.NOTHING);
 		if( values==null )
 //			throw parser.exception("Expressions expected");
 			return parser.failure(null);
 		return parser.success( makeSetStmt(vars,values) );
 	}
 
-	private StmtString makeSetStmt(List<Var> vars,ExpString values) throws ParseException {
+	private Stmts makeSetStmt(List<Var> vars,Expr values) throws ParseException {
 		int n = vars.size();
 		if( n == 1 )
 			return vars.get(0).set(values);
-		StmtString stmt = new StmtString();
-		stmt.list.add( "t = " );
+		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" );
-		ExpString t = new ExpString(values.isExpr,false);
-		t.list.add( "t" );
+		Expr t = new Expr(values.valType,false);
+		t.list.add( varName );
+		t = t.single();
 		stmt.list.addAll( vars.get(0).set(t).list );
 		for( int i=1; i<n; i++ ) {
 			t.list.clear();
-			t.list.add( "LuanImpl.pick(t,"+i+")" );
+			t.list.add( "LuanImpl.pick(" + varName + ","+i+")" );
 			stmt.list.addAll( vars.get(i).set(t).list );
 		}
 		return stmt;
 	}
 
-	private StmtString makeLocalSetStmt(List<String> names,ExpString values) throws ParseException {
+	private Stmts makeLocalSetStmt(List<String> names,Expr values) throws ParseException {
 		int n = names.size();
 		if( n == 1 )
-			return addSymbol(names.get(0),values.expr());
-		StmtString stmt = new StmtString();
-		stmt.list.add( "t = " );
+			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" );
-		ExpString t = new ExpString(values.isExpr,false);
-		t.list.add( "t" );
-		stmt.list.addAll( addSymbol(names.get(0),t.expr()).list );
+		Expr t = new Expr(values.valType,false);
+		t.list.add( varName );
+		t = t.single();
+		stmt.list.addAll( addSymbol(names.get(0),t).list );
 		for( int i=1; i<n; i++ ) {
 			t.list.clear();
-			t.list.add( "LuanImpl.pick(t,"+i+")" );
+			t.list.add( "LuanImpl.pick(" + varName + ","+i+")" );
 			stmt.list.addAll( addSymbol(names.get(i),t).list );
 		}
 		return stmt;
 	}
 
-	private StmtString ExpressionsStmt() throws ParseException {
+	private Stmts ExpressionsStmt() throws ParseException {
 		parser.begin();
-		ExpString exp = ExprZ(In.NOTHING);
+		Expr exp = ExprZ(In.NOTHING);
 		if( exp != null && exp.isStmt ) {
-			StmtString stmt = new StmtString();
-			if( exp.isExpr ) {
+			Stmts stmt = new Stmts();
+			if( exp.valType==Val.SINGLE ) {
 				stmt.list.add( "LuanImpl.nop(" );
 				stmt.list.addAll( exp.list );
 				stmt.list.add( ")" );
@@ -742,24 +739,24 @@
 		return parser.success( var );
 	}
 
-	private ExpString RequiredExpr(In in) throws ParseException {
+	private Expr RequiredExpr(In in) throws ParseException {
 		parser.begin();
 		return parser.success(required(ExprZ(in),"Bad expression"));
 	}
 
-	private ExpString ExprZ(In in) throws ParseException {
+	private Expr ExprZ(In in) throws ParseException {
 		return OrExpr(in);
 	}
 
-	private ExpString OrExpr(In in) throws ParseException {
+	private Expr OrExpr(In in) throws ParseException {
 		parser.begin();
-		ExpString exp = AndExpr(in);
+		Expr exp = AndExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		while( Keyword("or",in) ) {
-			exp = exp.expr();
-			ExpString exp2 = required(RelExpr(in)).expr();
-			ExpString newExp = new ExpString(true,true);
+			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 : (" );
@@ -770,15 +767,15 @@
 		return parser.success(exp);
 	}
 
-	private ExpString AndExpr(In in) throws ParseException {
+	private Expr AndExpr(In in) throws ParseException {
 		parser.begin();
-		ExpString exp = RelExpr(in);
+		Expr exp = RelExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		while( Keyword("and",in) ) {
-			exp = exp.expr();
-			ExpString exp2 = required(RelExpr(in)).expr();
-			ExpString newExp = new ExpString(true,true);
+			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( ") ? (" );
@@ -789,17 +786,17 @@
 		return parser.success(exp);
 	}
 
-	private ExpString RelExpr(In in) throws ParseException {
+	private Expr RelExpr(In in) throws ParseException {
 		parser.begin();
-		ExpString exp = ConcatExpr(in);
+		Expr exp = ConcatExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		while(true) {
 			if( parser.match("==") ) {
 				Spaces(in);
-				exp = exp.expr();
-				ExpString exp2 = required(ConcatExpr(in)).expr();
-				ExpString newExp = new ExpString(true,false);
+				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( "," );
@@ -808,9 +805,9 @@
 				exp = newExp;
 			} else if( parser.match("~=") ) {
 				Spaces(in);
-				exp = exp.expr();
-				ExpString exp2 = required(ConcatExpr(in)).expr();
-				ExpString newExp = new ExpString(true,false);
+				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( "," );
@@ -819,9 +816,9 @@
 				exp = newExp;
 			} else if( parser.match("<=") ) {
 				Spaces(in);
-				exp = exp.expr();
-				ExpString exp2 = required(ConcatExpr(in)).expr();
-				ExpString newExp = new ExpString(true,false);
+				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( "," );
@@ -830,9 +827,9 @@
 				exp = newExp;
 			} else if( parser.match(">=") ) {
 				Spaces(in);
-				exp = exp.expr();
-				ExpString exp2 = required(ConcatExpr(in)).expr();
-				ExpString newExp = new ExpString(true,false);
+				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( "," );
@@ -841,9 +838,9 @@
 				exp = newExp;
 			} else if( parser.match("<") ) {
 				Spaces(in);
-				exp = exp.expr();
-				ExpString exp2 = required(ConcatExpr(in)).expr();
-				ExpString newExp = new ExpString(true,false);
+				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( "," );
@@ -852,9 +849,9 @@
 				exp = newExp;
 			} else if( parser.match(">") ) {
 				Spaces(in);
-				exp = exp.expr();
-				ExpString exp2 = required(ConcatExpr(in)).expr();
-				ExpString newExp = new ExpString(true,false);
+				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( "," );
@@ -867,16 +864,16 @@
 		return parser.success(exp);
 	}
 
-	private ExpString ConcatExpr(In in) throws ParseException {
+	private Expr ConcatExpr(In in) throws ParseException {
 		parser.begin();
-		ExpString exp = SumExpr(in);
+		Expr exp = SumExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		if( parser.match("..") ) {
 			Spaces(in);
-			exp = exp.expr();
-			ExpString exp2 = required(ConcatExpr(in)).expr();
-			ExpString newExp = new ExpString(true,false);
+			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( "," );
@@ -887,17 +884,17 @@
 		return parser.success(exp);
 	}
 
-	private ExpString SumExpr(In in) throws ParseException {
+	private Expr SumExpr(In in) throws ParseException {
 		parser.begin();
-		ExpString exp = TermExpr(in);
+		Expr exp = TermExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		while(true) {
 			if( parser.match('+') ) {
 				Spaces(in);
-				exp = exp.expr();
-				ExpString exp2 = required(TermExpr(in)).expr();
-				ExpString newExp = new ExpString(true,false);
+				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( "," );
@@ -906,9 +903,9 @@
 				exp = newExp;
 			} else if( Minus() ) {
 				Spaces(in);
-				exp = exp.expr();
-				ExpString exp2 = required(TermExpr(in)).expr();
-				ExpString newExp = new ExpString(true,false);
+				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( "," );
@@ -926,17 +923,17 @@
 		return parser.match('-') && !parser.match('-') ? parser.success() : parser.failure();
 	}
 
-	private ExpString TermExpr(In in) throws ParseException {
+	private Expr TermExpr(In in) throws ParseException {
 		parser.begin();
-		ExpString exp = UnaryExpr(in);
+		Expr exp = UnaryExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		while(true) {
 			if( parser.match('*') ) {
 				Spaces(in);
-				exp = exp.expr();
-				ExpString exp2 = required(UnaryExpr(in)).expr();
-				ExpString newExp = new ExpString(true,false);
+				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( "," );
@@ -945,9 +942,9 @@
 				exp = newExp;
 			} else if( parser.match('/') ) {
 				Spaces(in);
-				exp = exp.expr();
-				ExpString exp2 = required(UnaryExpr(in)).expr();
-				ExpString newExp = new ExpString(true,false);
+				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( "," );
@@ -956,9 +953,9 @@
 				exp = newExp;
 			} else if( Mod() ) {
 				Spaces(in);
-				exp = exp.expr();
-				ExpString exp2 = required(UnaryExpr(in)).expr();
-				ExpString newExp = new ExpString(true,false);
+				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( "," );
@@ -976,12 +973,12 @@
 		return parser.match('%') && !parser.match('>') ? parser.success() : parser.failure();
 	}
 
-	private ExpString UnaryExpr(In in) throws ParseException {
+	private Expr UnaryExpr(In in) throws ParseException {
 		parser.begin();
 		if( parser.match('#') ) {
 			Spaces(in);
-			ExpString exp = required(UnaryExpr(in)).expr();
-			ExpString newExp = new ExpString(true,false);
+			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( ")" );
@@ -989,8 +986,8 @@
 		}
 		if( Minus() ) {
 			Spaces(in);
-			ExpString exp = required(UnaryExpr(in)).expr();
-			ExpString newExp = new ExpString(true,false);
+			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( ")" );
@@ -998,41 +995,41 @@
 		}
 		if( Keyword("not",in) ) {
 			Spaces(in);
-			ExpString exp = required(UnaryExpr(in)).expr();
-			ExpString newExp = new ExpString(true,false);
+			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( ")" );
 			return parser.success(newExp);
 		}
-		ExpString exp = PowExpr(in);
+		Expr exp = PowExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		return parser.success(exp);
 	}
 
-	private ExpString PowExpr(In in) throws ParseException {
+	private Expr PowExpr(In in) throws ParseException {
 		parser.begin();
-		ExpString exp1 = SingleExpr(in);
+		Expr exp1 = SingleExpr(in);
 		if( exp1==null )
 			return parser.failure(null);
 		if( parser.match('^') ) {
 			Spaces(in);
-			ExpString exp2 = required(PowExpr(in));
-			ExpString newExp = new ExpString(true,false);
+			Expr exp2 = required(PowExpr(in));
+			Expr newExp = new Expr(Val.SINGLE,false);
 			newExp.list.add( "LuanImpl.pow(luan," );
-			newExp.list.addAll( exp1.expr().list );
+			newExp.list.addAll( exp1.single().list );
 			newExp.list.add( "," );
-			newExp.list.addAll( exp2.expr().list );
+			newExp.list.addAll( exp2.single().list );
 			newExp.list.add( ")" );
 			exp1 = newExp;
 		}
 		return parser.success(exp1);
 	}
 
-	private ExpString SingleExpr(In in) throws ParseException {
+	private Expr SingleExpr(In in) throws ParseException {
 		parser.begin();
-		ExpString exp = FunctionExpr(in);
+		Expr exp = FunctionExpr(in);
 		if( exp != null )
 			return parser.success(exp);
 		exp = VarExp(in);
@@ -1044,22 +1041,22 @@
 		return parser.failure(null);
 	}
 
-	private ExpString FunctionExpr(In in) throws ParseException {
+	private Expr FunctionExpr(In in) throws ParseException {
 		if( !Keyword("function",in) )
 			return null;
 		return RequiredFunction(in);
 	}
 
-	private ExpString RequiredFunction(In in) throws ParseException {
+	private Expr RequiredFunction(In in) throws ParseException {
 		int start = parser.begin();
 		RequiredMatch('(');
 		In inParens = in.parens();
 		Spaces(inParens);
 		frame = new Frame(frame);
-		StmtString stmt = new StmtString();
+		Stmts stmt = new Stmts();
 		List<String> names = NameList(in);
 		if( names != null ) {
-			ExpString args = new ExpString(false,false);
+			Expr args = new Expr(Val.ARRAY,false);
 			args.list.add( "args" );
 			stmt.list.addAll( makeLocalSetStmt(names,args).list );
 			if( parser.match(',') ) {
@@ -1077,45 +1074,45 @@
 		}
 		RequiredMatch(')');
 		Spaces(in);
-		StmtString block = RequiredBlock();
+		Stmts block = RequiredBlock();
 		stmt.list.addAll( block.list );
 		stmt.hasReturn = block.hasReturn;
 		RequiredKeyword("end",in);
-		ExpString fnDef = newFnExpStr(start,stmt);
+		Expr fnDef = newFnExpStr(start,stmt);
 		frame = frame.parent;
 		return parser.success(fnDef);
 	}
 
-	private ExpString VarArgs(In in) throws ParseException {
+	private Expr VarArgs(In in) throws ParseException {
 		parser.begin();
 		if( !frame.isVarArg || !parser.match("...") )
 			return parser.failure(null);
 		Spaces(in);
-		ExpString exp = new ExpString(false,false);
+		Expr exp = new Expr(Val.ARRAY,false);
 		exp.list.add("varArgs");
 		return parser.success(exp);
 	}
 
-	private ExpString TableExpr(In in) throws ParseException {
+	private Expr TableExpr(In in) throws ParseException {
 		parser.begin();
 		if( !parser.match('{') )
 			return parser.failure(null);
 		Spaces(In.NOTHING);
-		List<ExpString> builder = new ArrayList<ExpString>();
+		List<Expr> builder = new ArrayList<Expr>();
 		Field(builder);
 		while( FieldSep() ) {
 			Spaces(In.NOTHING);
 			Field(builder);
 		}
-		ExpString exp = TemplateExpressions(In.NOTHING);
+		Expr exp = TemplateExpressions(In.NOTHING);
 		if( exp != null )
 			builder.add(exp);
 		if( !parser.match('}') )
 			throw parser.exception("Expected table element or '}'");
 		Spaces(in);
-		exp = new ExpString(true,false);
+		exp = new Expr(Val.SINGLE,false);
 		exp.list.add( "LuanImpl.table(" );
-		exp.list.addAll( expString(builder).list );
+		exp.list.addAll( expString(builder).array().list );
 		exp.list.add( ")" );
 		return parser.success( exp );
 	}
@@ -1124,15 +1121,15 @@
 		return parser.anyOf(",;") || EndOfLine();
 	}
 
-	private boolean Field(List<ExpString> builder) throws ParseException {
+	private boolean Field(List<Expr> builder) throws ParseException {
 		parser.begin();
-		ExpString exp = SubExpr(In.NOTHING);
+		Expr exp = SubExpr(In.NOTHING);
 		if( exp==null )
 			exp = NameExpr(In.NOTHING);
 		if( exp!=null && parser.match('=') ) {
 			Spaces(In.NOTHING);
-			ExpString val = RequiredExpr(In.NOTHING).expr();
-			ExpString newExp = new ExpString(true,false);
+			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( "," );
@@ -1142,7 +1139,7 @@
 			return parser.success();
 		}
 		parser.rollback();
-		ExpString exprs = ExprZ(In.NOTHING);
+		Expr exprs = ExprZ(In.NOTHING);
 		if( exprs != null ) {
 			builder.add(exprs);
 			return parser.success();
@@ -1150,7 +1147,7 @@
 		return parser.failure();
 	}
 
-	private ExpString VarExp(In in) throws ParseException {
+	private Expr VarExp(In in) throws ParseException {
 		Var var = VarZ(in);
 		return var==null ? null : var.exp();
 	}
@@ -1171,7 +1168,7 @@
 		if( parser.match('(') ) {
 			In inParens = in.parens();
 			Spaces(inParens);
-			ExpString exp = RequiredExpr(inParens).expr();
+			Expr exp = RequiredExpr(inParens).single();
 			RequiredMatch(')');
 			Spaces(in);
 			return exprVar(exp);
@@ -1179,7 +1176,7 @@
 		String name = Name(in);
 		if( name != null )
 			return nameVar(name);
-		ExpString exp;
+		Expr exp;
 		exp = TableExpr(in);
 		if( exp != null )
 			return exprVar(exp);
@@ -1189,9 +1186,9 @@
 		return null;
 	}
 
-	private Var Var2(In in,ExpString exp1) throws ParseException {
+	private Var Var2(In in,Expr exp1) throws ParseException {
 		parser.begin();
-		ExpString exp2 = SubExpr(in);
+		Expr exp2 = SubExpr(in);
 		if( exp2 != null )
 			return parser.success(indexVar(exp1,exp2));
 		if( parser.match('.') ) {
@@ -1201,20 +1198,20 @@
 				return parser.success(indexVar(exp1,exp2));
 			return parser.failure(null);
 		}
-		ExpString fnCall = Args( in, exp1, new ArrayList<ExpString>() );
+		Expr fnCall = Args( in, exp1, new ArrayList<Expr>() );
 		if( fnCall != null )
 			return parser.success(exprVar(fnCall));
 		return parser.failure(null);
 	}
 
 	private interface Var {
-		public ExpString exp() throws ParseException;
+		public Expr exp() throws ParseException;
 //		public Settable settable() throws ParseException;
 		public boolean isSettable();
-		public StmtString set(ExpString val) throws ParseException;
+		public Stmts set(Expr val) throws ParseException;
 	}
 
-	private ExpString env() {
+	private Expr env() {
 		Sym sym = getSym("_ENV");
 		if( sym != null )
 			return sym.exp();
@@ -1224,11 +1221,11 @@
 	private Var nameVar(final String name) {
 		return new Var() {
 
-			public ExpString exp() throws ParseException {
+			public Expr exp() throws ParseException {
 				Sym sym = getSym(name);
 				if( sym != null )
 					return sym.exp();
-				ExpString envExpr = env();
+				Expr envExpr = env();
 				if( envExpr != null )
 					return indexExpStr( envExpr, constExpStr(name) );
 				parser.failure(null);
@@ -1238,32 +1235,18 @@
 			public boolean isSettable() {
 				return true;
 			}
-/*
-			private Settable settable() throws ParseException {
-				int index = stackIndex(name);
-				if( index != -1 )
-					return new SetLocalVar(index);
-				index = upValueIndex(name);
-				if( index != -1 )
-					return new SetUpVar(index);
-				Expr envExpr = env();
-				if( envExpr != null )
-					return new SetTableEntry( envExpr, new ConstExpr(name) );
-				parser.failure(null);
-				throw parser.exception("name '"+name+"' not defined");
-			}
-*/
-			public StmtString set(ExpString val) throws ParseException {
+
+			public Stmts set(Expr val) throws ParseException {
 				Sym sym = getSym(name);
 				if( sym != null ) {
-					StmtString stmt = new StmtString();
+					Stmts stmt = new Stmts();
 					stmt.list.addAll( sym.exp().list );
 					stmt.list.add( " = " );
-					stmt.list.addAll( val.expr().list );
+					stmt.list.addAll( val.single().list );
 					stmt.list.add( ";\n" );
 					return stmt;
 				}
-				ExpString envExpr = env();
+				Expr envExpr = env();
 				if( envExpr != null )
 					return indexVar( envExpr, constExpStr(name) ).set(val);
 				throw new RuntimeException();
@@ -1271,10 +1254,10 @@
 		};
 	}
 
-	private Var exprVar(final ExpString expr) {
+	private Var exprVar(final Expr expr) {
 		return new Var() {
 
-			public ExpString exp() {
+			public Expr exp() {
 				return expr;
 			}
 
@@ -1282,49 +1265,45 @@
 				return false;
 			}
 
-			public StmtString set(ExpString val) {
+			public Stmts set(Expr val) {
 				throw new RuntimeException();
 			}
 		};
 	}
 
-	private Var indexVar(final ExpString table,final ExpString key) {
+	private Var indexVar(final Expr table,final Expr key) {
 		return new Var() {
 
-			public ExpString exp() {
+			public Expr exp() {
 				return indexExpStr( table, key );
 			}
 
 			public boolean isSettable() {
 				return true;
 			}
-/*
-			public Settable settable() {
-				return new SetTableEntry(expr(LuanParser.exp(table)),expr(LuanParser.exp(key)));
-			}
-*/
-			public StmtString set(ExpString val) {
-				StmtString stmt = new StmtString();
+
+			public Stmts set(Expr val) {
+				Stmts stmt = new Stmts();
 				stmt.list.add( "LuanImpl.put(luan," );
-				stmt.list.addAll( table.expr().list );
+				stmt.list.addAll( table.single().list );
 				stmt.list.add( "," );
-				stmt.list.addAll( key.expr().list );
+				stmt.list.addAll( key.single().list );
 				stmt.list.add( "," );
-				stmt.list.addAll( val.expr().list );
+				stmt.list.addAll( val.single().list );
 				stmt.list.add( ");\n" );
 				return stmt;
 			}
 		};
 	}
 
-	private ExpString Args(In in,ExpString fn,List<ExpString> builder) throws ParseException {
+	private Expr Args(In in,Expr fn,List<Expr> builder) throws ParseException {
 		parser.begin();
 		return args(in,builder)
 			? parser.success( callExpStr( fn, expString(builder) ) )
-			: parser.failure((ExpString)null);
+			: parser.failure((Expr)null);
 	}
 
-	private boolean args(In in,List<ExpString> builder) throws ParseException {
+	private boolean args(In in,List<Expr> builder) throws ParseException {
 		parser.begin();
 		if( parser.match('(') ) {
 			In inParens = in.parens();
@@ -1335,7 +1314,7 @@
 			Spaces(in);
 			return parser.success();
 		}
-		ExpString exp = TableExpr(in);
+		Expr exp = TableExpr(in);
 		if( exp != null ) {
 			builder.add(exp);
 			return parser.success();
@@ -1355,14 +1334,14 @@
 		return parser.failure();
 	}
 
-	private ExpString ExpStringList(In in) throws ParseException {
-		List<ExpString> builder = new ArrayList<ExpString>();
+	private Expr ExpStringList(In in) throws ParseException {
+		List<Expr> builder = new ArrayList<Expr>();
 		return ExpList(in,builder) ? expString(builder) : null;
 	}
 
-	private boolean ExpList(In in,List<ExpString> builder) throws ParseException {
+	private boolean ExpList(In in,List<Expr> builder) throws ParseException {
 		parser.begin();
-		ExpString exp = TemplateExpressions(in);
+		Expr exp = TemplateExpressions(in);
 		if( exp != null ) {
 			builder.add(exp);
 			return parser.success();
@@ -1383,18 +1362,18 @@
 		return parser.success();
 	}
 
-	private ExpString SubExpr(In in) throws ParseException {
+	private Expr SubExpr(In in) throws ParseException {
 		parser.begin();
 		if( !parser.match('[') || parser.test("[") || parser.test("=") )
 			return parser.failure(null);
 		Spaces(In.NOTHING);
-		ExpString exp = RequiredExpr(In.NOTHING).expr();
+		Expr exp = RequiredExpr(In.NOTHING).single();
 		RequiredMatch(']');
 		Spaces(in);
 		return parser.success(exp);
 	}
 
-	private ExpString NameExpr(In in) throws ParseException {
+	private Expr NameExpr(In in) throws ParseException {
 		parser.begin();
 		String name = Name(in);
 		if( name==null )
@@ -1478,16 +1457,16 @@
 		"while"
 	));
 
-	private ExpString Literal(In in) throws ParseException {
+	private Expr Literal(In in) throws ParseException {
 		parser.begin();
 		if( NilLiteral(in) ) {
-			ExpString exp = new ExpString(true,false);
+			Expr exp = new Expr(Val.SINGLE,false);
 			exp.list.add( "null" );
 			return parser.success(exp);
 		}
 		Boolean b = BooleanLiteral(in);
 		if( b != null ) {
-			ExpString exp = new ExpString(true,false);
+			Expr exp = new Expr(Val.SINGLE,false);
 			exp.list.add( b.toString() );
 			return parser.success(exp);
 		}
@@ -1496,7 +1475,7 @@
 			String s = n.toString();
 			if( n instanceof Long )
 				s += "L";
-			ExpString exp = new ExpString(true,false);
+			Expr exp = new Expr(Val.SINGLE,false);
 			exp.list.add( s );
 			return parser.success(exp);
 		}
@@ -1506,7 +1485,7 @@
 		return parser.failure(null);
 	}
 
-	private ExpString constExpStr(String s) {
+	private Expr constExpStr(String s) {
 		s = s
 			.replace("\\","\\\\")
 			.replace("\"","\\\"")
@@ -1515,7 +1494,7 @@
 			.replace("\t","\\t")
 			.replace("\b","\\b")
 		;
-		ExpString exp = new ExpString(true,false);
+		Expr exp = new Expr(Val.SINGLE,false);
 		exp.list.add( "\""+s+"\"" );
 		return exp;
 	}
@@ -1769,37 +1748,48 @@
 
 	private static int classCounter = 0;
 
-	private class ExpString {
+	private enum Val { SINGLE, ARRAY }
+
+	private class Expr {
 		final List list = new ArrayList();
-		final boolean isExpr;
+		final Val valType;
 		final boolean isStmt;
-/*
-		ExpString(Expressions exp) {
-			if( exp==null )  throw new NullPointerException();
-			int i = LuanImpl.addObj(exp);
-			list.add( "((Expressions)LuanImpl.getObj(" + i + ")).eval(luan)" );
-			isExpr = exp instanceof Expr;
-			isStmt = exp instanceof StmtExp;
-		}
-*/
-		ExpString(boolean isExpr,boolean isStmt) {
-			this.isExpr = isExpr;
+
+		Expr(Val valType,boolean isStmt) {
+			this.valType = valType;
 			this.isStmt = isStmt;
 		}
 
-		ExpString expr() {
-			if( isExpr )
+		Expr single() {
+			if( valType==Val.SINGLE )
 				return this;
-			ExpString exp = new ExpString(true,isStmt);
-			exp.list.add( "Luan.first(" );
+			Expr exp = new Expr(Val.SINGLE,isStmt);
+			exp.list.add( valType==Val.ARRAY ? "LuanImpl.first(" : "Luan.first(" );
 			exp.list.addAll( list );
 			exp.list.add( ")" );
 			return exp;
 		}
+
+		Expr array() {
+			if( valType==Val.ARRAY )
+				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( "}" );
+			} else {
+				exp.list.add( "Luan.array(" );
+				exp.list.addAll( list );
+				exp.list.add( ")" );
+			}
+			return exp;
+		}
+
 	}
 
-	private ExpString expString(List<ExpString> list) {
-		ExpString exp = new ExpString(false,false);
+	private Expr expString(List<Expr> list) {
+		Expr exp = new Expr(Val.ARRAY,false);
 		switch(list.size()) {
 		case 0:
 			exp.list.add("LuanFunction.NOTHING");
@@ -1810,11 +1800,11 @@
 			int lastI = list.size() - 1;
 			exp.list.add( "new Object[]{" );
 			for( int i=0; i<lastI; i++ ) {
-				exp.list.addAll( list.get(i).expr().list );
+				exp.list.addAll( list.get(i).single().list );
 				exp.list.add( "," );
 			}
-			ExpString last = list.get(lastI);
-			if( last.isExpr ) {
+			Expr last = list.get(lastI);
+			if( last.valType==Val.SINGLE ) {
 				exp.list.addAll( last.list );
 				exp.list.add( "}" );
 			} else {
@@ -1828,7 +1818,7 @@
 		}
 	}
 
-	private static class StmtString {
+	private static class Stmts {
 		final List list = new ArrayList();
 		boolean hasReturn = false;
 	}
@@ -1837,14 +1827,14 @@
 		StringBuilder sb = new StringBuilder();
 		for( Object o : list ) {
 			if( o instanceof List )  throw new RuntimeException();
-			if( o instanceof ExpString )  throw new RuntimeException();
-			if( o instanceof StmtString )  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(StmtString stmt,List<UpSym> upValueSymbols) {
+	private Class toFnClass(Stmts stmt,List<UpSym> upValueSymbols) {
 		String code = concat(stmt.list);
 //System.out.println("code:\n"+code);
 
@@ -1866,6 +1856,7 @@
 			+"\n"
 			+"	@Override public Object doCall(LuanState luan,Object[] args) throws LuanException {\n"
 			+"		Object t;\n"
+			+"		Object[] a;\n"
 			+"		" + code
 			+"	}\n"
 			+"}\n"
@@ -1879,8 +1870,8 @@
 		}
 	}
 
-	private ExpString toFnExpStr(StmtString stmt,List<UpSym> upValueSymbols) {
-		ExpString exp = new ExpString(true,false);
+	private Expr toFnExpStr(Stmts stmt,List<UpSym> upValueSymbols) {
+		Expr exp = new Expr(Val.SINGLE,false);
 		exp.list.add( ""
 			+"\n"
 			+"new Closure("+upValueSymbols.size()+",java) {\n"
@@ -1889,6 +1880,7 @@
 			+"}\n"
 			+"	@Override public Object doCall(LuanState luan,Object[] args) throws LuanException {\n"
 			+"		Object t;\n"
+			+"		Object[] a;\n"
 			+"		"
 		);
 		exp.list.addAll( stmt.list );
@@ -1907,11 +1899,4 @@
 		return sb.toString();
 	}
 
-/*
-	private static String settableToString(Settable settable) {
-		if( settable==null )  throw new NullPointerException();
-		int i = LuanImpl.addObj(settable);
-		return"((Settable)LuanImpl.getObj(" + i + "))";
-	}
-*/
 }