changeset 111:2428ecfed375

change LuanFunction.call() from returning Object[] to returning Object, to reduce garbage collection git-svn-id: https://luan-java.googlecode.com/svn/trunk@112 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Fri, 23 May 2014 20:40:05 +0000
parents 7afa6df829f3
children f5af13062b10
files src/luan/Luan.java src/luan/LuanBit.java src/luan/LuanFunction.java src/luan/LuanJavaFunction.java src/luan/LuanState.java src/luan/interp/Closure.java src/luan/interp/ExpList.java src/luan/interp/Expressions.java src/luan/interp/FnCall.java src/luan/interp/GenericForStmt.java src/luan/interp/LuanCompiler.java src/luan/interp/LuanStateImpl.java src/luan/interp/SetStmt.java src/luan/interp/TableExpr.java src/luan/lib/BasicLib.java src/luan/lib/PackageLib.java src/luan/tools/CmdLine.java src/luan/tools/WebShell.java
diffstat 18 files changed, 111 insertions(+), 84 deletions(-) [+]
line wrap: on
line diff
--- a/src/luan/Luan.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/Luan.java	Fri May 23 20:40:05 2014 +0000
@@ -4,6 +4,17 @@
 public final class Luan {
 	public static final String version = "Luan 0.1";
 
+	public static Object first(Object obj) {
+		if( !(obj instanceof Object[]) )
+			return obj;
+		Object[] a = (Object[])obj;
+		return a.length==0 ? null : a[0];
+	}
+
+	public static Object[] array(Object obj) {
+		return obj instanceof Object[] ? (Object[])obj : new Object[]{obj};
+	}
+
 	public static String type(Object obj) {
 		if( obj == null )
 			return "nil";
@@ -51,10 +62,6 @@
 		return null;
 	}
 
-	public static Object first(Object[] a) {
-		return a.length==0 ? null : a[0];
-	}
-
 	public static String toString(Number n) {
 		if( n instanceof Integer )
 			return n.toString();
--- a/src/luan/LuanBit.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/LuanBit.java	Fri May 23 20:40:05 2014 +0000
@@ -16,7 +16,7 @@
 		return new LuanException(this,msg);
 	}
 
-	public Object[] call(LuanFunction fn,String fnName,Object... args) throws LuanException {
+	public Object call(LuanFunction fn,String fnName,Object... args) throws LuanException {
 		List<StackTraceElement> stackTrace = luan.stackTrace;
 		stackTrace.add( new StackTraceElement(el,fnName) );
 		try {
--- a/src/luan/LuanFunction.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/LuanFunction.java	Fri May 23 20:40:05 2014 +0000
@@ -3,7 +3,7 @@
 
 public abstract class LuanFunction {
 
-	public abstract Object[] call(LuanState luan,Object[] args) throws LuanException;
+	public abstract Object call(LuanState luan,Object[] args) throws LuanException;
 
 	public static final Object[] EMPTY = new Object[0];
 
--- a/src/luan/LuanJavaFunction.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/LuanJavaFunction.java	Fri May 23 20:40:05 2014 +0000
@@ -49,7 +49,7 @@
 		return method.getParameterTypes();
 	}
 
-	@Override public Object[] call(LuanState luan,Object[] args) throws LuanException {
+	@Override public Object call(LuanState luan,Object[] args) throws LuanException {
 		args = fixArgs(luan,args);
 		try {
 			return doCall(luan,args);
@@ -59,12 +59,12 @@
 		}
 	}
 
-	public Object[] rawCall(LuanState luan,Object[] args) throws LuanException {
+	public Object rawCall(LuanState luan,Object[] args) throws LuanException {
 		args = fixArgs(luan,args);
 		return doCall(luan,args);
 	}
 
-	private Object[] doCall(LuanState luan,Object[] args) throws LuanException {
+	private Object doCall(LuanState luan,Object[] args) throws LuanException {
 		Object rtn;
 		try {
 			rtn = method.invoke(obj,args);
@@ -158,35 +158,25 @@
 
 
 	private interface RtnConverter {
-		public Object[] convert(Object obj);
+		public Object convert(Object obj);
 	}
 
 	private static final RtnConverter RTN_EMPTY = new RtnConverter() {
-		public Object[] convert(Object obj) {
+		@Override public Object[] convert(Object obj) {
 			return EMPTY;
 		}
 	};
 
-	private static final RtnConverter RTN_ARRAY = new RtnConverter() {
-		public Object[] convert(Object obj) {
-			if( obj == null )
-				return NULL_RTN;
-			return (Object[])obj;
+	private static final RtnConverter RTN_SAME = new RtnConverter() {
+		@Override public Object convert(Object obj) {
+			return obj;
 		}
 	};
 
-	private static final RtnConverter RTN_ONE = new RtnConverter() {
-		public Object[] convert(Object obj) {
-			return new Object[]{obj};
-		}
-	};
-
-	private static final Object[] NULL_RTN = new Object[1];
-
 	private static final RtnConverter RTN_NUMBER_ARRAY = new RtnConverter() {
-		public Object[] convert(Object obj) {
+		@Override public Object convert(Object obj) {
 			if( obj == null )
-				return NULL_RTN;
+				return null;
 			Object[] rtn = new Object[Array.getLength(obj)];
 			for( int i=0; i<rtn.length; i++ ) {
 				rtn[i] = Array.get(obj,i);
@@ -199,13 +189,9 @@
 		Class<?> rtnType = m.getReturnType();
 		if( rtnType == Void.TYPE )
 			return RTN_EMPTY;
-		if( rtnType.isArray() ) {
-			rtnType = rtnType.getComponentType();
-			if( isNumber(rtnType) )
-				return RTN_NUMBER_ARRAY;
-			return RTN_ARRAY;
-		}
-		return RTN_ONE;
+		if( rtnType.isArray() && isNumber(rtnType.getComponentType()) )
+			return RTN_NUMBER_ARRAY;
+		return RTN_SAME;
 	}
 
 	private static boolean isNumber(Class<?> rtnType) {
--- a/src/luan/LuanState.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/LuanState.java	Fri May 23 20:40:05 2014 +0000
@@ -121,7 +121,7 @@
 		}
 	}
 
-	public final Object[] eval(String cmd,String sourceName,boolean interactive) throws LuanException {
+	public final Object eval(String cmd,String sourceName,boolean interactive) throws LuanException {
 		LuanFunction fn = BasicLib.load(this,cmd,sourceName,interactive);
 		return JAVA.call(fn,null);
 	}
--- a/src/luan/interp/Closure.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/interp/Closure.java	Fri May 23 20:40:05 2014 +0000
@@ -1,5 +1,6 @@
 package luan.interp;
 
+import luan.Luan;
 import luan.LuanFunction;
 import luan.LuanState;
 import luan.LuanElement;
@@ -37,11 +38,11 @@
 		return upValues;
 	}
 
-	public Object[] call(LuanState luan,Object[] args) throws LuanException {
+	@Override public Object call(LuanState luan,Object[] args) throws LuanException {
 		return call(this,(LuanStateImpl)luan,args);
 	}
 
-	private static Object[] call(Closure closure,LuanStateImpl luan,Object[] args) throws LuanException {
+	private static Object call(Closure closure,LuanStateImpl luan,Object[] args) throws LuanException {
 		while(true) {
 			FnDef fnDef = closure.fnDef;
 			Object[] varArgs = null;
@@ -60,7 +61,7 @@
 			for( int i=0; i<n; i++ ) {
 				stack[i] = args[i];
 			}
-			Object[] returnValues;
+			Object returnValues;
 			Closure tailFn;
 			try {
 				fnDef.block.eval(luan);
@@ -72,7 +73,7 @@
 			}
 			if( closure == null )
 				return returnValues;
-			args = returnValues;
+			args = Luan.array(returnValues);
 		}
 	}
 
--- a/src/luan/interp/ExpList.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/interp/ExpList.java	Fri May 23 20:40:05 2014 +0000
@@ -39,8 +39,13 @@
 		}
 
 		public void addTo(LuanStateImpl luan,List<Object> list) throws LuanException {
-			for( Object val : expressions.eval(luan) ) {
-				list.add( val );
+			Object obj = expressions.eval(luan);
+			if( obj instanceof Object[] ) {
+				for( Object val : (Object[])obj ) {
+					list.add( val );
+				}
+			} else {
+				list.add(obj);
 			}
 		}
 
@@ -115,8 +120,8 @@
 			this.expr = expr;
 		}
 
-		@Override public Object[] eval(LuanStateImpl luan) throws LuanException {
-			return new Object[]{expr.eval(luan)};
+		@Override public Object eval(LuanStateImpl luan) throws LuanException {
+			return expr.eval(luan);
 		}
 
 		@Override public LuanSource.Element se() {
@@ -130,12 +135,19 @@
 		this.adders = adders;
 	}
 
-	@Override public Object[] eval(LuanStateImpl luan) throws LuanException {
+	@Override public Object eval(LuanStateImpl luan) throws LuanException {
 		List<Object> list = new ArrayList<Object>();
 		for( Adder adder : adders ) {
 			adder.addTo(luan,list);
 		}
-		return list.toArray();
+		switch( list.size() ) {
+		case 0:
+			return EMPTY;
+		case 1:
+			return list.get(0);
+		default:
+			return list.toArray();
+		}
 	}
 
 	@Override public LuanSource.Element se() {
--- a/src/luan/interp/Expressions.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/interp/Expressions.java	Fri May 23 20:40:05 2014 +0000
@@ -4,5 +4,5 @@
 
 
 interface Expressions extends Code {
-	public Object[] eval(LuanStateImpl luan) throws LuanException;
+	public Object eval(LuanStateImpl luan) throws LuanException;
 }
--- a/src/luan/interp/FnCall.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/interp/FnCall.java	Fri May 23 20:40:05 2014 +0000
@@ -18,11 +18,11 @@
 		this.fnName = fnExpr.se().text();
 	}
 
-	@Override public Object[] eval(LuanStateImpl luan) throws LuanException {
+	@Override public Object eval(LuanStateImpl luan) throws LuanException {
 		return call( luan, fnExpr.eval(luan) );
 	}
 
-	private Object[] call(LuanStateImpl luan,Object o) throws LuanException {
+	private Object call(LuanStateImpl luan,Object o) throws LuanException {
 		if( o instanceof LuanFunction ) {
 			LuanFunction fn = (LuanFunction)o;
 			return luan.bit(se).call( fn, fnName, args.eval(luan) );
--- a/src/luan/interp/GenericForStmt.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/interp/GenericForStmt.java	Fri May 23 20:40:05 2014 +0000
@@ -27,11 +27,21 @@
 		String name = iterExpr.se().text();
 		try {
 			while(true) {
-				Object[] vals = bit.call(iter,name);
-				if( vals.length==0 || vals[0]==null )
+				Object vals = bit.call(iter,name);
+				if( vals==null )
 					break;
-				for( int i=0; i<nVars; i++ ) {
-					luan.stackSet( iVars+i, i < vals.length ? vals[i] : null );
+				if( vals instanceof Object[] ) {
+					Object[] a = (Object[])vals;
+					if( a.length==0 )
+						break;
+					for( int i=0; i<nVars; i++ ) {
+						luan.stackSet( iVars+i, i < a.length ? a[i] : null );
+					}
+				} else {
+					luan.stackSet( iVars, vals );
+					for( int i=1; i<nVars; i++ ) {
+						luan.stackSet( iVars+i, null );
+					}
 				}
 				block.eval(luan);
 			}
--- a/src/luan/interp/LuanCompiler.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/interp/LuanCompiler.java	Fri May 23 20:40:05 2014 +0000
@@ -25,9 +25,11 @@
 			FnDef fnDef = parser.RequiredModule();
 			final Closure c = new Closure((LuanStateImpl)luan,fnDef);
 			return new LuanFunction() {
-				public Object[] call(LuanState luan,Object[] args) throws LuanException {
-					Object[] rtn = c.call(luan,args);
-					return rtn.length==0 ? new Object[]{c.upValues()[0].get()} : rtn;
+				@Override public Object call(LuanState luan,Object[] args) throws LuanException {
+					Object rtn = c.call(luan,args);
+					if( rtn instanceof Object[] && ((Object[])rtn).length==0 )
+						rtn = c.upValues()[0].get();
+					return rtn;
 				}
 			};
 		} catch(ParseException e) {
--- a/src/luan/interp/LuanStateImpl.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/interp/LuanStateImpl.java	Fri May 23 20:40:05 2014 +0000
@@ -55,7 +55,7 @@
 	}
 
 	private Frame frame = null;
-	Object[] returnValues = LuanFunction.EMPTY;
+	Object returnValues = LuanFunction.EMPTY;
 	Closure tailFn;
 	Map<UpValue.EnvGetter,UpValue> envs = new HashMap<UpValue.EnvGetter,UpValue>();
 
--- a/src/luan/interp/SetStmt.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/interp/SetStmt.java	Fri May 23 20:40:05 2014 +0000
@@ -18,10 +18,18 @@
 	}
 
 	@Override public void eval(LuanStateImpl luan) throws LuanException {
-		final Object[] vals = expressions.eval(luan);
-		for( int i=0; i<vars.length; i++ ) {
-			Object val = i < vals.length ? vals[i] : null;
-			vars[i].set(luan,val);
+		final Object obj = expressions.eval(luan);
+		if( obj instanceof Object[] ) {
+			Object[] vals = (Object[])obj;
+			for( int i=0; i<vars.length; i++ ) {
+				Object val = i < vals.length ? vals[i] : null;
+				vars[i].set(luan,val);
+			}
+		} else {
+			vars[0].set(luan,obj);
+			for( int i=1; i<vars.length; i++ ) {
+				vars[i].set(luan,null);
+			}
 		}
 	}
 
--- a/src/luan/interp/TableExpr.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/interp/TableExpr.java	Fri May 23 20:40:05 2014 +0000
@@ -31,9 +31,14 @@
 		for( Field field : fields ) {
 			table.put( field.key.eval(luan), field.value.eval(luan) );
 		}
-		Object[] a = expressions.eval(luan);
-		for( int i=0; i<a.length; i++ ) {
-			table.put( i+1, a[i] );
+		Object obj = expressions.eval(luan);
+		if( obj instanceof Object[] ) {
+			Object[] a = (Object[])obj;
+			for( int i=0; i<a.length; i++ ) {
+				table.put( i+1, a[i] );
+			}
+		} else {
+			table.put( 1, obj );
 		}
 		return table;
 	}
--- a/src/luan/lib/BasicLib.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/lib/BasicLib.java	Fri May 23 20:40:05 2014 +0000
@@ -22,7 +22,7 @@
 	public static final String NAME = "Basic";
 
 	public static final LuanFunction LOADER = new LuanFunction() {
-		@Override public Object[] call(LuanState luan,Object[] args) {
+		@Override public Object call(LuanState luan,Object[] args) {
 			LuanTable module = new LuanTable();
 			LuanTable global = luan.global();
 			try {
@@ -54,7 +54,7 @@
 			} catch(NoSuchMethodException e) {
 				throw new RuntimeException(e);
 			}
-			return new Object[]{module};
+			return module;
 		}
 	};
 
@@ -92,7 +92,7 @@
 		}
 	}
 
-	public static Object[] do_file(LuanState luan,String fileName) throws LuanException {
+	public static Object do_file(LuanState luan,String fileName) throws LuanException {
 		LuanFunction fn = load_file(luan,fileName);
 		return luan.JAVA.call(fn,null);
 	}
--- a/src/luan/lib/PackageLib.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/lib/PackageLib.java	Fri May 23 20:40:05 2014 +0000
@@ -19,7 +19,7 @@
 	public static final String NAME = "Package";
 
 	public static final LuanFunction LOADER = new LuanFunction() {
-		@Override public Object[] call(LuanState luan,Object[] args) {
+		@Override public Object call(LuanState luan,Object[] args) {
 			LuanTable module = new LuanTable();
 			LuanTable global = luan.global();
 			module.put("loaded",luan.loaded());
@@ -36,7 +36,7 @@
 			searchers.add(fileSearcher);
 			searchers.add(javaFileSearcher);
 			module.put("searchers",searchers);
-			return new Object[]{module};
+			return module;
 		}
 	};
 
@@ -62,7 +62,7 @@
 				searchers = new LuanTable(Collections.<Object>singletonList(preloadSearcher));
 			for( Object s : searchers.asList() ) {
 				LuanFunction searcher = (LuanFunction)s;
-				Object[] a = luan.JAVA.call(searcher,"<searcher>",modName);
+				Object[] a = Luan.array(luan.JAVA.call(searcher,"<searcher>",modName));
 				if( a.length >= 1 && a[0] instanceof LuanFunction ) {
 					LuanFunction loader = (LuanFunction)a[0];
 					a[0] = modName;
@@ -93,11 +93,10 @@
 	}
 
 	public static final LuanFunction fileLoader = new LuanFunction() {
-		@Override public Object[] call(LuanState luan,Object[] args) throws LuanException {
-			String modName = (String)args[0];
+		@Override public Object call(LuanState luan,Object[] args) throws LuanException {
 			String fileName = (String)args[1];
 			LuanFunction fn = BasicLib.load_file(luan,fileName);
-			return fn.call(luan,new Object[]{args[0],fileName});
+			return fn.call(luan,args);
 		}
 	};
 
@@ -124,13 +123,13 @@
 
 
 	public static final LuanFunction javaFileLoader = new LuanFunction() {
-		@Override public Object[] call(LuanState luan,Object[] args) throws LuanException {
-			String modName = (String)args[0];
-			URL url = (URL)args[0];
+		@Override public Object call(LuanState luan,Object[] args) throws LuanException {
+			String urlStr = (String)args[1];
 			try {
+				URL url = new URL(urlStr);
 				String src = Utils.read(url);
-				LuanFunction fn = BasicLib.load(luan,src,url.toString(),false);
-				return fn.call(luan,new Object[]{args[0],url.toString()});
+				LuanFunction fn = BasicLib.load(luan,src,urlStr,false);
+				return fn.call(luan,args);
 			} catch(IOException e) {
 				throw luan.JAVA.exception(e);
 			}
@@ -147,7 +146,7 @@
 				String file = s.replaceAll("\\?",modName);
 				URL url = ClassLoader.getSystemResource(file);
 				if( url != null ) {
-					return new Object[]{javaFileLoader,url};
+					return new Object[]{javaFileLoader,url.toString()};
 				}
 			}
 			return LuanFunction.EMPTY;
--- a/src/luan/tools/CmdLine.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/tools/CmdLine.java	Fri May 23 20:40:05 2014 +0000
@@ -101,7 +101,7 @@
 				if( input==null )
 					break;
 				try {
-					Object[] rtn = luan.eval(input,"stdin",true);
+					Object[] rtn = Luan.array(luan.eval(input,"stdin",true));
 					if( rtn.length > 0 )
 						BasicLib.print(luan,rtn);
 				} catch(LuanException e) {
--- a/src/luan/tools/WebShell.java	Fri May 23 04:36:47 2014 +0000
+++ b/src/luan/tools/WebShell.java	Fri May 23 20:40:05 2014 +0000
@@ -13,6 +13,7 @@
 import javax.servlet.http.HttpSession;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import luan.Luan;
 import luan.LuanFunction;
 import luan.LuanState;
 import luan.LuanTable;
@@ -27,13 +28,9 @@
 	protected LuanState newLuanState() throws LuanException {
 		return LuanState.newStandard();
 	}
-/*
-	protected LuanTable newEnvironment(LuanState luan) throws LuanException {
-		return luan.newEnvironment();
-	}
-*/
+
 	protected Object[] eval(LuanState luan,String cmd) throws LuanException {
-		return luan.eval(cmd,"WebShell",true);
+		return Luan.array(luan.eval(cmd,"WebShell",true));
 	}
 
 	@Override protected void service(HttpServletRequest request,HttpServletResponse response)