changeset 154:c2e5101682ae

Expr extends Expressions git-svn-id: https://luan-java.googlecode.com/svn/trunk@155 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Tue, 17 Jun 2014 09:55:43 +0000
parents fa03671f59a0
children db7b3902e01c
files src/luan/interp/ExpList.java src/luan/interp/Expr.java src/luan/interp/LuanParser.java src/luan/interp/SetStmt.java
diffstat 4 files changed, 118 insertions(+), 185 deletions(-) [+]
line wrap: on
line diff
--- a/src/luan/interp/ExpList.java	Tue Jun 17 02:57:14 2014 +0000
+++ b/src/luan/interp/ExpList.java	Tue Jun 17 09:55:43 2014 +0000
@@ -2,110 +2,19 @@
 
 import java.util.List;
 import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Arrays;
 import luan.LuanException;
 import luan.LuanSource;
+import luan.LuanFunction;
+import luan.Luan;
 
 
-final class ExpList implements Expressions {
-
-	private interface Adder {
-		public void addTo(LuanStateImpl luan,List<Object> list) throws LuanException;
-		public Code code();
-	}
-
-	private static class ExprAdder implements Adder {
-		private final Expr expr;
-
-		ExprAdder(Expr expr) {
-			this.expr = expr;
-		}
-
-		public void addTo(LuanStateImpl luan,List<Object> list) throws LuanException {
-			list.add( expr.eval(luan) );
-		}
-
-		public Code code() {
-			return expr;
-		}
-
-	}
-
-	private static class ExpressionsAdder implements Adder {
-		private final Expressions expressions;
-
-		ExpressionsAdder(Expressions expressions) {
-			this.expressions = expressions;
-		}
-
-		public void addTo(LuanStateImpl luan,List<Object> list) throws LuanException {
-			Object obj = expressions.eval(luan);
-			if( obj instanceof Object[] ) {
-				for( Object val : (Object[])obj ) {
-					list.add( val );
-				}
-			} else {
-				list.add(obj);
-			}
-		}
-
-		public Code code() {
-			return expressions;
-		}
-
-	}
-
-	static class Builder {
-		private final List<Adder> adders = new ArrayList<Adder>();
-
-		void add(Expr expr) {
-			if( expr==null )
-				throw new NullPointerException();
-			adders.add( new ExprAdder(expr) );
-		}
-
-		void add(Expressions expressions) {
-			adders.add( new ExpressionsAdder(expressions) );
-		}
-
-		void add(Code code) {
-			if( code instanceof Expr ) {
-				add((Expr)code);
-			} else {
-				add((Expressions)code);
-			}
-		}
-
-		Expressions build() {
-			int size = adders.size();
-			if( size == 0 )
-				return emptyExpList;
-			if( size == 1 ) {
-				Adder adder = adders.get(0);
-				if( adder instanceof ExpressionsAdder ) {
-					ExpressionsAdder ea = (ExpressionsAdder)adder;
-					return ea.expressions;
-				}
-				ExprAdder ea = (ExprAdder)adder;
-				return new SingleExpList(ea.expr);
-			}
-			Adder[] a = adders.toArray(new Adder[size]);
-			for( int i=0; i<size-1; i++ ) {
-				Adder adder = a[i];
-				if( adder instanceof ExpressionsAdder ) {
-					a[i] = new ExprAdder(new ExpressionsExpr(((ExpressionsAdder)adder).expressions));
-				}
-			}
-			return new ExpList(a);
-		}
-	}
-
-	private static final Object[] EMPTY = new Object[0];
+final class ExpList {
 
 	static final Expressions emptyExpList = new Expressions() {
 
 		@Override public Object[] eval(LuanStateImpl luan) {
-			return EMPTY;
+			return LuanFunction.NOTHING;
 		}
 
 		@Override public LuanSource.Element se() {
@@ -113,49 +22,75 @@
 		}
 	};
 
-	static class SingleExpList implements Expressions {
-		private final Expr expr;
-
-		SingleExpList(Expr expr) {
-			this.expr = expr;
+	static Expr[] toArray(List<Expressions> list) {
+		Expr[] a = new Expr[list.size()];
+		for( int i=0; i<a.length; i++ ) {
+			Expressions exprs = list.get(i);
+			if( exprs instanceof Expr ) {
+				a[i] = (Expr)exprs;
+			} else {
+				a[i] = new ExpressionsExpr(exprs);
+			}
 		}
+		return a;
+	}
 
-		@Override public Object eval(LuanStateImpl luan) throws LuanException {
-//System.out.println("SingleExpList "+expr);
-			return expr.eval(luan);
-		}
-
-		@Override public LuanSource.Element se() {
-			return expr.se();
-		}
-
-		@Override public String toString() {
-			return "(SingleExpList "+expr+")";
+	static Expressions build(List<Expressions> list) {
+		switch(list.size()) {
+		case 0:
+			return emptyExpList;
+		case 1:
+			return list.get(0);
+		default:
+			if( list.get(list.size()-1) instanceof Expr ) {
+				return new ExprList1( toArray(list) );
+			} else {
+				Expressions last = list.remove(list.size()-1);
+				return new ExprList2( toArray(list), last );
+			}
 		}
 	}
 
-	private final Adder[] adders;
-
-	private ExpList(Adder[] adders) {
-		this.adders = adders;
-	}
+	private static class ExprList1 implements Expressions {
+		private final Expr[] exprs;
 
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		List<Object> list = new ArrayList<Object>();
-		for( Adder adder : adders ) {
-			adder.addTo(luan,list);
+		private ExprList1(Expr[] exprs) {
+			this.exprs = exprs;
 		}
-		switch( list.size() ) {
-		case 0:
-			return EMPTY;
-		case 1:
-			return list.get(0);
-		default:
-			return list.toArray();
+	
+		@Override public Object eval(LuanStateImpl luan) throws LuanException {
+			Object[] a = new Object[exprs.length];
+			for( int i=0; i<exprs.length; i++ ) {
+				a[i] = exprs[i].eval(luan);
+			}
+			return a;
+		}
+	
+		@Override public LuanSource.Element se() {
+			return new LuanSource.Element(exprs[0].se().source,exprs[0].se().start,exprs[exprs.length-1].se().end);
 		}
 	}
 
-	@Override public LuanSource.Element se() {
-		return new LuanSource.Element(adders[0].code().se().source,adders[0].code().se().start,adders[adders.length-1].code().se().end);
+	private static class ExprList2 implements Expressions {
+		private final Expr[] exprs;
+		private final Expressions last;
+	
+		private ExprList2(Expr[] exprs,Expressions last) {
+			this.exprs = exprs;
+			this.last = last;
+		}
+	
+		@Override public Object eval(LuanStateImpl luan) throws LuanException {
+			List<Object> list = new ArrayList<Object>();
+			for( Expr expr : exprs ) {
+				list.add( expr.eval(luan) );
+			}
+			list.addAll( Arrays.asList(Luan.array( last.eval(luan) )) );
+			return list.toArray();
+		}
+	
+		@Override public LuanSource.Element se() {
+			return new LuanSource.Element(exprs[0].se().source,exprs[0].se().start,last.se().end);
+		}
 	}
 }
--- a/src/luan/interp/Expr.java	Tue Jun 17 02:57:14 2014 +0000
+++ b/src/luan/interp/Expr.java	Tue Jun 17 09:55:43 2014 +0000
@@ -3,6 +3,4 @@
 import luan.LuanException;
 
 
-interface Expr extends Code {
-	public Object eval(LuanStateImpl luan) throws LuanException;
-}
+interface Expr extends Expressions {}
--- a/src/luan/interp/LuanParser.java	Tue Jun 17 02:57:14 2014 +0000
+++ b/src/luan/interp/LuanParser.java	Tue Jun 17 09:55:43 2014 +0000
@@ -170,10 +170,10 @@
 		return t;
 	}
 
-	private static Expr expr(Code code) {
-		if( code instanceof Expressions )
-			return new ExpressionsExpr((Expressions)code);
-		return (Expr)code;
+	private static Expr expr(Expressions exprs) {
+		if( exprs instanceof Expr )
+			return (Expr)exprs; 
+		return new ExpressionsExpr(exprs);
 	}
 
 	private FnDef newFnDef(int start,Stmt stmt) {
@@ -263,7 +263,7 @@
 			return parser.failure(null);
 		EndOfLine();
 		In inJsp = in.jsp();
-		ExpList.Builder builder = new ExpList.Builder();
+		List<Expressions> builder = new ArrayList<Expressions>();
 		while(true) {
 			if( parser.match( "<%=" ) ) {
 				Spaces(inJsp);
@@ -271,7 +271,7 @@
 				RequiredMatch( "%>" );
 			} else if( parser.match( "<%" ) ) {
 				Spaces(inJsp);
-				return parser.success(builder.build());
+				return parser.success(ExpList.build(builder));
 			} else {
 				int i = parser.currentIndex();
 				do {
@@ -333,7 +333,7 @@
 			return parser.failure(null);
 		String varName = modName.substring(modName.lastIndexOf('.')+1);
 		LuanSource.Element se = se(start);
-		FnCall require = new FnCall( se, importExpr, new ExpList.SingleExpList(new ConstExpr(modName)) );
+		FnCall require = new FnCall( se, importExpr, new ConstExpr(modName) );
 		Settable settable;
 		if( interactive ) {
 			settable = new SetTableEntry( se(start), env(), new ConstExpr(varName) );
@@ -540,25 +540,25 @@
 		return var.settable();
 	}
 
-	private Code RequiredExpr(In in) throws ParseException {
+	private Expressions RequiredExpr(In in) throws ParseException {
 		parser.begin();
 		return parser.success(required(Expr(in),"Bad expression"));
 	}
 
-	private Code Expr(In in) throws ParseException {
+	private Expressions Expr(In in) throws ParseException {
 		parser.begin();
-		Code exp;
+		Expressions exp;
 		return (exp = VarArgs(in)) != null
 			|| (exp = JspExpressions(in)) != null
 			|| (exp = OrExpr(in)) != null
 			? parser.success(exp)
-			: parser.failure((Code)null)
+			: parser.failure((Expressions)null)
 		;
 	}
 
-	private Code OrExpr(In in) throws ParseException {
+	private Expressions OrExpr(In in) throws ParseException {
 		int start = parser.begin();
-		Code exp = AndExpr(in);
+		Expressions exp = AndExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		while( Keyword("or",in) ) {
@@ -567,9 +567,9 @@
 		return parser.success(exp);
 	}
 
-	private Code AndExpr(In in) throws ParseException {
+	private Expressions AndExpr(In in) throws ParseException {
 		int start = parser.begin();
-		Code exp = RelExpr(in);
+		Expressions exp = RelExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		while( Keyword("and",in) ) {
@@ -578,9 +578,9 @@
 		return parser.success(exp);
 	}
 
-	private Code RelExpr(In in) throws ParseException {
+	private Expressions RelExpr(In in) throws ParseException {
 		int start = parser.begin();
-		Code exp = ConcatExpr(in);
+		Expressions exp = ConcatExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		while(true) {
@@ -608,9 +608,9 @@
 		return parser.success(exp);
 	}
 
-	private Code ConcatExpr(In in) throws ParseException {
+	private Expressions ConcatExpr(In in) throws ParseException {
 		int start = parser.begin();
-		Code exp = SumExpr(in);
+		Expressions exp = SumExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		if( parser.match("..") ) {
@@ -620,9 +620,9 @@
 		return parser.success(exp);
 	}
 
-	private Code SumExpr(In in) throws ParseException {
+	private Expressions SumExpr(In in) throws ParseException {
 		int start = parser.begin();
-		Code exp = TermExpr(in);
+		Expressions exp = TermExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		while(true) {
@@ -643,9 +643,9 @@
 		return parser.match('-') && !parser.match('-') ? parser.success() : parser.failure();
 	}
 
-	private Code TermExpr(In in) throws ParseException {
+	private Expressions TermExpr(In in) throws ParseException {
 		int start = parser.begin();
-		Code exp = UnaryExpr(in);
+		Expressions exp = UnaryExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		while(true) {
@@ -669,7 +669,7 @@
 		return parser.match('%') && !parser.match('>') ? parser.success() : parser.failure();
 	}
 
-	private Code UnaryExpr(In in) throws ParseException {
+	private Expressions UnaryExpr(In in) throws ParseException {
 		int start = parser.begin();
 		if( parser.match('#') ) {
 			Spaces(in);
@@ -683,15 +683,15 @@
 			Spaces(in);
 			return parser.success( new NotExpr( se(start), required(expr(UnaryExpr(in))) ) );
 		}
-		Code exp = PowExpr(in);
+		Expressions exp = PowExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		return parser.success(exp);
 	}
 
-	private Code PowExpr(In in) throws ParseException {
+	private Expressions PowExpr(In in) throws ParseException {
 		int start = parser.begin();
-		Code exp = SingleExpr(in);
+		Expressions exp = SingleExpr(in);
 		if( exp==null )
 			return parser.failure(null);
 		if( parser.match('^') ) {
@@ -701,9 +701,9 @@
 		return parser.success(exp);
 	}
 
-	private Code SingleExpr(In in) throws ParseException {
+	private Expressions SingleExpr(In in) throws ParseException {
 		parser.begin();
-		Code exp;
+		Expressions exp;
 		exp = FunctionExpr(in);
 		if( exp != null )
 			return parser.success(exp);
@@ -768,12 +768,12 @@
 		In inParens = in.parens();
 		Spaces(inParens);
 		List<TableExpr.Field> fields = new ArrayList<TableExpr.Field>();
-		ExpList.Builder builder = new ExpList.Builder();
+		List<Expressions> builder = new ArrayList<Expressions>();
 		while( Field(fields,builder,in) && FieldSep(inParens) );
 		Spaces(inParens);
 		if( !parser.match('}') )
 			throw parser.exception("Expected table element or '}'");
-		return parser.success( new TableExpr( se(start), fields.toArray(new TableExpr.Field[0]), builder.build() ) );
+		return parser.success( new TableExpr( se(start), fields.toArray(new TableExpr.Field[0]), ExpList.build(builder) ) );
 	}
 
 	private boolean FieldSep(In in) throws ParseException {
@@ -783,7 +783,7 @@
 		return true;
 	}
 
-	private boolean Field(List<TableExpr.Field> fields,ExpList.Builder builder,In in) throws ParseException {
+	private boolean Field(List<TableExpr.Field> fields,List<Expressions> builder,In in) throws ParseException {
 		parser.begin();
 		Expr exp = SubExpr(in);
 		if( exp==null )
@@ -794,15 +794,15 @@
 			return parser.success();
 		}
 		parser.rollback();
-		Code code = Expr(in);
-		if( code != null ) {
-			builder.add(code);
+		Expressions exprs = Expr(in);
+		if( exprs != null ) {
+			builder.add(exprs);
 			return parser.success();
 		}
 		return parser.failure();
 	}
 
-	private Code VarExp(In in) throws ParseException {
+	private Expressions VarExp(In in) throws ParseException {
 		Var var = VarZ(in);
 		return var==null ? null : var.expr();
 	}
@@ -819,25 +819,25 @@
 		return parser.success(var);
 	}
 
-	private Var Var2(In in,int start,Code exp1) throws ParseException {
+	private Var Var2(In in,int start,Expressions exp1) throws ParseException {
 		Var var = VarExt(in,start,exp1);
 		if( var != null )
 			return var;
 		if( parser.match("->") ) {
 			Spaces(in);
-			ExpList.Builder builder = new ExpList.Builder();
+			List<Expressions> builder = new ArrayList<Expressions>();
 			builder.add(exp1);
 			Expr exp2 = expr(RequiredVarExpB(in));
 			FnCall fnCall = required(Args( in, start, exp2, builder ));
 			return exprVar(fnCall);
 		}
-		FnCall fnCall = Args( in, start, expr(exp1), new ExpList.Builder() );
+		FnCall fnCall = Args( in, start, expr(exp1), new ArrayList<Expressions>() );
 		if( fnCall != null )
 			return exprVar(fnCall);
 		return null;
 	}
 
-	private Code RequiredVarExpB(In in) throws ParseException {
+	private Expressions RequiredVarExpB(In in) throws ParseException {
 		int start = parser.begin();
 		Var var = required(VarStart(in));
 		Var var2;
@@ -847,7 +847,7 @@
 		return parser.success(var.expr());
 	}
 
-	private Var VarExt(In in,int start,Code exp1) throws ParseException {
+	private Var VarExt(In in,int start,Expressions exp1) throws ParseException {
 		parser.begin();
 		Expr exp2 = SubExpr(in);
 		if( exp2 != null )
@@ -888,7 +888,7 @@
 	}
 
 	private interface Var {
-		public Code expr();
+		public Expressions expr();
 		public Settable settable();
 	}
 
@@ -917,10 +917,10 @@
 		};
 	}
 
-	private Var exprVar(final Code expr) {
+	private Var exprVar(final Expressions expr) {
 		return new Var() {
 
-			public Code expr() {
+			public Expressions expr() {
 				return expr;
 			}
 
@@ -943,14 +943,14 @@
 		};
 	}
 
-	private FnCall Args(In in,int start,Expr fn,ExpList.Builder builder) throws ParseException {
+	private FnCall Args(In in,int start,Expr fn,List<Expressions> builder) throws ParseException {
 		parser.begin();
 		return args(in,builder)
-			? parser.success( new FnCall( se(start), fn, builder.build() ) )
+			? parser.success( new FnCall( se(start), fn, ExpList.build(builder) ) )
 			: parser.failure((FnCall)null);
 	}
 
-	private boolean args(In in,ExpList.Builder builder) throws ParseException {
+	private boolean args(In in,List<Expressions> builder) throws ParseException {
 		if( parser.match('(') ) {
 			In inParens = in.parens();
 			Spaces(inParens);
@@ -979,13 +979,13 @@
 	}
 
 	private Expressions ExpList(In in) throws ParseException {
-		ExpList.Builder builder = new ExpList.Builder();
-		return ExpList(in,builder) ? builder.build() : null;
+		List<Expressions> builder = new ArrayList<Expressions>();
+		return ExpList(in,builder) ? ExpList.build(builder) : null;
 	}
 
-	private boolean ExpList(In in,ExpList.Builder builder) throws ParseException {
+	private boolean ExpList(In in,List<Expressions> builder) throws ParseException {
 		parser.begin();
-		Code exp = Expr(in);
+		Expressions exp = Expr(in);
 		if( exp==null )
 			return parser.failure();
 		builder.add(exp);
--- a/src/luan/interp/SetStmt.java	Tue Jun 17 02:57:14 2014 +0000
+++ b/src/luan/interp/SetStmt.java	Tue Jun 17 09:55:43 2014 +0000
@@ -9,7 +9,7 @@
 	private final Expressions expressions;
 
 	SetStmt(Settable var,Expr expr) {
-		this( new Settable[]{var}, new ExpList.SingleExpList(expr) );
+		this( new Settable[]{var}, expr );
 	}
 
 	SetStmt(Settable[] vars,Expressions expressions) {