changeset 646:cdc70de628b5

simplify LuanException
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 29 Mar 2016 19:58:39 -0600
parents 859c0dedc8b6
children 8e8c30b72e9b
files core/src/luan/LuanException.java core/src/luan/LuanJavaFunction.java core/src/luan/LuanPropertyMeta.java core/src/luan/LuanState.java core/src/luan/LuanTable.java core/src/luan/impl/BinaryOpExpr.java core/src/luan/impl/Closure.java core/src/luan/impl/FnCall.java core/src/luan/impl/LeExpr.java core/src/luan/impl/LenExpr.java core/src/luan/impl/LuanCompiler.java core/src/luan/impl/LuanStateImpl.java core/src/luan/impl/SetTableEntry.java core/src/luan/impl/ThemeParser.java core/src/luan/impl/UnmExpr.java core/src/luan/modules/BasicLuan.java core/src/luan/modules/BinaryLuan.java core/src/luan/modules/HtmlLuan.java core/src/luan/modules/IoLuan.java core/src/luan/modules/JavaLuan.java core/src/luan/modules/PackageLuan.java core/src/luan/modules/RpcLuan.java core/src/luan/modules/StringLuan.java core/src/luan/modules/TableLuan.java core/src/luan/modules/ThreadLuan.java core/src/luan/modules/Utils.java core/src/luan/modules/parsers/BBCode.java http/src/luan/modules/http/HttpServicer.java lucene/src/luan/modules/lucene/LuceneIndex.java mail/src/luan/modules/mail/SmtpCon.java
diffstat 30 files changed, 221 insertions(+), 208 deletions(-) [+]
line wrap: on
line diff
--- a/core/src/luan/LuanException.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/LuanException.java	Tue Mar 29 19:58:39 2016 -0600
@@ -7,15 +7,23 @@
 public final class LuanException extends Exception implements DeepCloneable {
 	private LuanTable table = new LuanTable();
 
-	private LuanException(String msg,Throwable cause) {
+	public LuanException(String msg,Throwable cause) {
 		super(msg,cause);
+		setTable();
 	}
 
-	public LuanException(LuanState luan,Object msg) throws LuanException {
-		this( luan.toString(msg), msg instanceof Throwable ? (Throwable)msg : null );
+	public LuanException(String msg) {
+		super(msg);
+		setTable();
+	}
+
+	public LuanException(Throwable cause) {
+		super(cause);
+		setTable();
+	}
+
+	private void setTable() {
 		table.rawPut( "java", this );
-		table.rawPut( "message", msg );
-		table.rawPut( "message_string", luan.toString(msg) );
 /*
 		for( StackTraceElement ste : luan.stackTrace ) {
 			LuanTable tbl = new LuanTable();
@@ -28,6 +36,9 @@
 		LuanTable metatable = new LuanTable();
 		table.setMetatable(metatable);
 		try {
+			table.rawPut( "get_message", new LuanJavaFunction(
+				LuanException.class.getMethod( "getMessage" ), this
+			) );
 			table.rawPut( "throw", new LuanJavaFunction(
 				LuanException.class.getMethod( "throwThis" ), this
 			) );
--- a/core/src/luan/LuanJavaFunction.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/LuanJavaFunction.java	Tue Mar 29 19:58:39 2016 -0600
@@ -70,19 +70,19 @@
 	@Override public Object call(LuanState luan,Object[] args) throws LuanException {
 		try {
 			args = fixArgs(luan,args);
-			return doCall(luan,args);
+			return doCall(args);
 		} catch(IllegalArgumentException e) {
-			checkArgs(luan,args);
+			checkArgs(args);
 			throw e;
 		}
 	}
 
 	public Object rawCall(LuanState luan,Object[] args) throws LuanException {
 		args = fixArgs(luan,args);
-		return doCall(luan,args);
+		return doCall(args);
 	}
 
-	private Object doCall(LuanState luan,Object[] args) throws LuanException {
+	private Object doCall(Object[] args) throws LuanException {
 		Object rtn;
 		try {
 			rtn = method.invoke(obj,args);
@@ -94,7 +94,7 @@
 				throw (Error)cause;
 			if( cause instanceof LuanException )
 				throw (LuanException)cause;
-			throw new LuanException(luan,cause);
+			throw new LuanException(cause);
 		} catch(InstantiationException e) {
 			throw new RuntimeException(e);
 		}
@@ -114,7 +114,7 @@
 		primitiveMap.put(Void.TYPE,Void.class);
 	}
 
-	private void checkArgs(LuanState luan,Object[] args) throws LuanException {
+	private void checkArgs(Object[] args) throws LuanException {
 		Class[] a = getParameterTypes();
 		int start = takesLuaState ? 1 : 0;
 		for( int i=start; i<a.length; i++ ) {
@@ -131,10 +131,10 @@
 					expected = fixType(paramType.getSimpleName());
 				if( arg==null ) {
 					if( paramType.isPrimitive() )
-						throw new LuanException(luan,"bad argument #"+(i+1-start)+" ("+expected+" expected, got nil)");
+						throw new LuanException("bad argument #"+(i+1-start)+" ("+expected+" expected, got nil)");
 				} else {
 					String got = fixType(arg.getClass().getSimpleName());
-					throw new LuanException(luan,"bad argument #"+(i+1-start)+" ("+expected+" expected, got "+got+")");
+					throw new LuanException("bad argument #"+(i+1-start)+" ("+expected+" expected, got "+got+")");
 				}
 			}
 		}
--- a/core/src/luan/LuanPropertyMeta.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/LuanPropertyMeta.java	Tue Mar 29 19:58:39 2016 -0600
@@ -26,7 +26,7 @@
 		if( obj == null )
 			return null;
 		if( !(obj instanceof LuanFunction) )
-			throw new LuanException(luan,"get for '"+key+"' isn't a function");
+			throw new LuanException("get for '"+key+"' isn't a function");
 		LuanFunction fn = (LuanFunction)obj;
 		return fn.call(luan);
 	}
@@ -59,7 +59,7 @@
 			return;
 		}
 		if( !(obj instanceof LuanFunction) )
-			throw new LuanException(luan,"set for '"+key+"' isn't a function");
+			throw new LuanException("set for '"+key+"' isn't a function");
 		LuanFunction fn = (LuanFunction)obj;
 		fn.call(luan,new Object[]{value});
 	}
--- a/core/src/luan/LuanState.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/LuanState.java	Tue Mar 29 19:58:39 2016 -0600
@@ -65,19 +65,19 @@
 	public Boolean checkBoolean(Object obj) throws LuanException {
 		if( obj instanceof Boolean )
 			return (Boolean)obj;
-		throw new LuanException(this, "attempt to use a " + Luan.type(obj) + " value as a boolean" );
+		throw new LuanException("attempt to use a " + Luan.type(obj) + " value as a boolean" );
 	}
 
 	public String checkString(Object obj) throws LuanException {
 		if( obj instanceof String )
 			return (String)obj;
-		throw new LuanException(this, "attempt to use a " + Luan.type(obj) + " value as a string" );
+		throw new LuanException("attempt to use a " + Luan.type(obj) + " value as a string" );
 	}
 
 	public LuanFunction checkFunction(Object obj) throws LuanException {
 		if( obj instanceof LuanFunction )
 			return (LuanFunction)obj;
-		throw new LuanException(this, "attempt to call a " + Luan.type(obj) + " value" );
+		throw new LuanException("attempt to call a " + Luan.type(obj) + " value" );
 	}
 
 	abstract public boolean isLessThan(Object o1,Object o2) throws LuanException;
@@ -103,7 +103,7 @@
 		}
 		if( obj != null && hasJava() )
 			return JavaLuan.__index(this,obj,key,false);
-		throw new LuanException(this, "attempt to index a " + Luan.type(obj) + " value" );
+		throw new LuanException("attempt to index a " + Luan.type(obj) + " value" );
 	}
 
 /*
--- a/core/src/luan/LuanTable.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/LuanTable.java	Tue Mar 29 19:58:39 2016 -0600
@@ -160,7 +160,7 @@
 			tbl.put(luan,key,value);
 			return;
 		}
-		throw new LuanException(luan,"invalid type "+Luan.type(h)+" for metamethod __new_index");
+		throw new LuanException("invalid type "+Luan.type(h)+" for metamethod __new_index");
 	}
 
 	public void rawPut(Object key,Object val) {
@@ -319,14 +319,14 @@
 				LuanFunction fn = (LuanFunction)h;
 				Object obj = Luan.first(fn.call(luan,new Object[]{this}));
 				if( !(obj instanceof LuanFunction) )
-					throw new LuanException(luan, "metamethod __pairs should return function but returned " + Luan.type(obj) );
+					throw new LuanException( "metamethod __pairs should return function but returned " + Luan.type(obj) );
 				return (LuanFunction)obj;
 			}
 			if( h instanceof LuanMeta ) {
 				LuanMeta meta = (LuanMeta)h;
 				return meta.__pairs(luan,this);
 			}
-			throw new LuanException(luan, "invalid type of metamethod __pairs: " + Luan.type(h) );
+			throw new LuanException( "invalid type of metamethod __pairs: " + Luan.type(h) );
 		}
 		return rawPairs();
 	}
--- a/core/src/luan/impl/BinaryOpExpr.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/impl/BinaryOpExpr.java	Tue Mar 29 19:58:39 2016 -0600
@@ -20,7 +20,7 @@
 		if( fn != null )
 			return Luan.first(fn.call(luan,new Object[]{o1,o2}));
 		String type = !(o1 instanceof Number) ? Luan.type(o1) : Luan.type(o2);
-		throw new LuanException(luan,"attempt to perform arithmetic on a "+type+" value");
+		throw new LuanException("attempt to perform arithmetic on a "+type+" value");
 	}
 
 }
--- a/core/src/luan/impl/Closure.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/impl/Closure.java	Tue Mar 29 19:58:39 2016 -0600
@@ -41,7 +41,7 @@
 		try {
 			return call(this,(LuanStateImpl)luan,args);
 		} catch(StackOverflowError e) {
-			throw new LuanException(luan, "stack overflow" );
+			throw new LuanException( "stack overflow", e );
 		}
 	}
 
--- a/core/src/luan/impl/FnCall.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/impl/FnCall.java	Tue Mar 29 19:58:39 2016 -0600
@@ -30,7 +30,7 @@
 			if( h != null )
 				return call(luan,h,argVals);
 		}
-		throw new LuanException(luan, "attempt to call a " + Luan.type(o) + " value" );
+		throw new LuanException( "attempt to call a " + Luan.type(o) + " value" );
 	}
 
 	@Override public String toString() {
--- a/core/src/luan/impl/LeExpr.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/impl/LeExpr.java	Tue Mar 29 19:58:39 2016 -0600
@@ -34,6 +34,6 @@
 		fn = luan.getBinHandler("__lt",o1,o2);
 		if( fn != null )
 			return !luan.checkBoolean( Luan.first(fn.call(luan,new Object[]{o2,o1})) );
-		throw new LuanException(luan, "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) );
+		throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) );
 	}
 }
--- a/core/src/luan/impl/LenExpr.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/impl/LenExpr.java	Tue Mar 29 19:58:39 2016 -0600
@@ -23,7 +23,7 @@
 			return a.length;
 		}
 		if( !(o instanceof LuanTable) )
-			throw new LuanException(luan, "attempt to get length of a " + Luan.type(o) + " value" );
+			throw new LuanException( "attempt to get length of a " + Luan.type(o) + " value" );
 		LuanTable t = (LuanTable)o;
 		return t.length(luan);
 	}
--- a/core/src/luan/impl/LuanCompiler.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/impl/LuanCompiler.java	Tue Mar 29 19:58:39 2016 -0600
@@ -16,12 +16,12 @@
 		LuanParser parser = new LuanParser(sourceName,sourceText,env);
 		parser.addVar( "java", JavaLuan.javaFn );
 		parser.addVar( "require", PackageLuan.requireFn );
-		FnDef fnDef = parse(luan,parser,allowExpr);
+		FnDef fnDef = parse(parser,allowExpr);
 		final LuanStateImpl luanImpl = (LuanStateImpl)luan;
 		return new Closure(luanImpl,fnDef);
 	}
 
-	private static FnDef parse(LuanState luan,LuanParser parser,boolean allowExpr) throws LuanException {
+	private static FnDef parse(LuanParser parser,boolean allowExpr) throws LuanException {
 		try {
 			if( allowExpr ) {
 				FnDef fnDef = parser.Expression();
@@ -31,7 +31,7 @@
 			return parser.RequiredModule();
 		} catch(ParseException e) {
 //e.printStackTrace();
-			throw new LuanException(luan, e.getFancyMessage() );
+			throw new LuanException( e.getFancyMessage() );
 		}
 	}
 
--- a/core/src/luan/impl/LuanStateImpl.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/impl/LuanStateImpl.java	Tue Mar 29 19:58:39 2016 -0600
@@ -132,7 +132,7 @@
 		LuanFunction fn = getBinHandler("__lt",o1,o2);
 		if( fn != null )
 			return checkBoolean( Luan.first(fn.call(this,new Object[]{o1,o2})) );
-		throw new LuanException(this, "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) );
+		throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) );
 	}
 
 	LuanFunction getBinHandler(String op,Object o1,Object o2) throws LuanException {
--- a/core/src/luan/impl/SetTableEntry.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/impl/SetTableEntry.java	Tue Mar 29 19:58:39 2016 -0600
@@ -30,7 +30,7 @@
 		if( t != null && luan.hasJava() )
 			JavaLuan.__new_index(luan,t,key,value);
 		else
-			throw new LuanException(luan, "attempt to index a " + Luan.type(t) + " value" );
+			throw new LuanException( "attempt to index a " + Luan.type(t) + " value" );
 	}
 
 }
--- a/core/src/luan/impl/ThemeParser.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/impl/ThemeParser.java	Tue Mar 29 19:58:39 2016 -0600
@@ -21,7 +21,7 @@
 			return new Closure(luanImpl,fnDef);
 		} catch(ParseException e) {
 //e.printStackTrace();
-			throw new LuanException(luan, e.getFancyMessage() );
+			throw new LuanException( e.getFancyMessage() );
 		}
 	}
 
@@ -202,7 +202,7 @@
 				@Override public Object eval(LuanStateImpl luan) throws LuanException {
 					Object obj = env.eval(luan);
 					if( !(obj instanceof LuanTable) )
-						throw new LuanException(luan,"bad argument (table expected, got "+Luan.type(obj)+")");
+						throw new LuanException("bad argument (table expected, got "+Luan.type(obj)+")");
 					LuanTable tbl = (LuanTable)obj;
 					String indent = (String)tbl.get(luan,INDENT);
 					if( indent==null )  throw new NullPointerException();
--- a/core/src/luan/impl/UnmExpr.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/impl/UnmExpr.java	Tue Mar 29 19:58:39 2016 -0600
@@ -23,6 +23,6 @@
 				return Luan.first(fn.call(luan,new Object[]{o}));
 			}
 		}
-		throw new LuanException(luan,"attempt to perform arithmetic on a "+Luan.type(o)+" value");
+		throw new LuanException("attempt to perform arithmetic on a "+Luan.type(o)+" value");
 	}
 }
--- a/core/src/luan/modules/BasicLuan.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/modules/BasicLuan.java	Tue Mar 29 19:58:39 2016 -0600
@@ -46,17 +46,17 @@
 			fileName = "stdin:";
 		String src = PackageLuan.read(luan,fileName,addExtension);
 		if( src == null )
-			throw new LuanException(luan, "file '"+fileName+"' not found" );
+			throw new LuanException("file '"+fileName+"' not found" );
 		return load(luan,src,fileName,null,false);
 	}
 
 	public static LuanFunction pairs(final LuanState luan,final LuanTable t) throws LuanException {
-		Utils.checkNotNull(luan,t);
+		Utils.checkNotNull(t);
 		return t.pairs(luan);
 	}
 
-	public static LuanFunction ipairs(LuanState luan,final LuanTable t) throws LuanException {
-		Utils.checkNotNull(luan,t);
+	public static LuanFunction ipairs(final LuanTable t) throws LuanException {
+		Utils.checkNotNull(t);
 		return new LuanFunction() {
 			List<Object> list = t.asList();
 			int i = 0;
@@ -71,8 +71,8 @@
 		};
 	}
 
-	public static Object get_metatable(LuanState luan,LuanTable table) throws LuanException {
-		Utils.checkNotNull(luan,table);
+	public static Object get_metatable(LuanTable table) throws LuanException {
+		Utils.checkNotNull(table);
 		LuanTable metatable = table.getMetatable();
 		if( metatable == null )
 			return null;
@@ -80,10 +80,10 @@
 		return obj!=null ? obj : metatable;
 	}
 
-	public static void set_metatable(LuanState luan,LuanTable table,LuanTable metatable) throws LuanException {
-		Utils.checkNotNull(luan,table);
+	public static void set_metatable(LuanTable table,LuanTable metatable) throws LuanException {
+		Utils.checkNotNull(table);
 		if( table.getHandler("__metatable") != null )
-			throw new LuanException(luan,"cannot change a protected metatable");
+			throw new LuanException("cannot change a protected metatable");
 		table.setMetatable(metatable);
 	}
 
@@ -99,7 +99,7 @@
 		table.rawPut(index,value);
 	}
 
-	public static int raw_len(LuanState luan,Object v) throws LuanException {
+	public static int raw_len(Object v) throws LuanException {
 		if( v instanceof String ) {
 			String s = (String)v;
 			return s.length();
@@ -108,7 +108,7 @@
 			LuanTable t = (LuanTable)v;
 			return t.rawLength();
 		}
-		throw new LuanException(luan, "bad argument #1 to 'raw_len' (table or string expected)" );
+		throw new LuanException( "bad argument #1 to 'raw_len' (table or string expected)" );
 	}
 
 	public static String to_string(LuanState luan,Object v) throws LuanException {
@@ -116,54 +116,57 @@
 	}
 
 	public static LuanTable new_error(LuanState luan,Object msg) throws LuanException {
-		return new LuanException(luan,msg).table();
+		String s = luan.toString(msg);
+		LuanTable tbl = new LuanException(s).table();
+		tbl.rawPut( "message", msg );
+		return tbl;
 	}
 
-	public static String assert_string(LuanState luan,String v) throws LuanException {
-		Utils.checkNotNull(luan,v);
+	public static String assert_string(String v) throws LuanException {
+		Utils.checkNotNull(v);
 		return v;
 	}
 
-	public static Number assert_number(LuanState luan,Number v) throws LuanException {
-		Utils.checkNotNull(luan,v);
+	public static Number assert_number(Number v) throws LuanException {
+		Utils.checkNotNull(v);
 		return v;
 	}
 
-	public static LuanTable assert_table(LuanState luan,LuanTable v) throws LuanException {
-		Utils.checkNotNull(luan,v);
+	public static LuanTable assert_table(LuanTable v) throws LuanException {
+		Utils.checkNotNull(v);
 		return v;
 	}
 
-	public static boolean assert_boolean(LuanState luan,boolean v) throws LuanException {
+	public static boolean assert_boolean(boolean v) throws LuanException {
 		return v;
 	}
 
-	public static int assert_integer(LuanState luan,int v) throws LuanException {
+	public static int assert_integer(int v) throws LuanException {
 		return v;
 	}
 
-	public static long assert_long(LuanState luan,long v) throws LuanException {
+	public static long assert_long(long v) throws LuanException {
 		return v;
 	}
 
-	public static double assert_double(LuanState luan,double v) throws LuanException {
+	public static double assert_double(double v) throws LuanException {
 		return v;
 	}
 
-	@LuanMethod public static byte[] assert_binary(LuanState luan,byte[] v) throws LuanException {
-		Utils.checkNotNull(luan,v);
+	@LuanMethod public static byte[] assert_binary(byte[] v) throws LuanException {
+		Utils.checkNotNull(v);
 		return v;
 	}
 
-	public static LuanFunction assert_function(LuanState luan,LuanFunction v) throws LuanException {
-		Utils.checkNotNull(luan,v);
+	public static LuanFunction assert_function(LuanFunction v) throws LuanException {
+		Utils.checkNotNull(v);
 		return v;
 	}
 
-	public static LuanFunction range(LuanState luan,final double from,final double to,Double stepV) throws LuanException {
+	public static LuanFunction range(final double from,final double to,Double stepV) throws LuanException {
 		final double step = stepV==null ? 1.0 : stepV;
 		if( step == 0.0 )
-			throw new LuanException(luan,"bad argument #3 (step may not be zero)");
+			throw new LuanException("bad argument #3 (step may not be zero)");
 		return new LuanFunction() {
 			double v = from;
 
@@ -194,25 +197,25 @@
 	}
 
 	public static Object try_(LuanState luan,LuanTable blocks,Object... args) throws LuanException {
-		Utils.checkNotNull(luan,blocks);
+		Utils.checkNotNull(blocks);
 		Object obj = blocks.get(luan,1);
 		if( obj == null )
-			throw new LuanException(luan,"missing 'try' value");
+			throw new LuanException("missing 'try' value");
 		if( !(obj instanceof LuanFunction) )
-			throw new LuanException(luan,"bad 'try' value (function expected, got "+Luan.type(obj)+")");
+			throw new LuanException("bad 'try' value (function expected, got "+Luan.type(obj)+")");
 		LuanFunction tryFn = (LuanFunction)obj;
 		LuanFunction catchFn = null;
 		obj = blocks.get(luan,"catch");
 		if( obj != null ) {
 			if( !(obj instanceof LuanFunction) )
-				throw new LuanException(luan,"bad 'catch' value (function expected, got "+Luan.type(obj)+")");
+				throw new LuanException("bad 'catch' value (function expected, got "+Luan.type(obj)+")");
 			catchFn = (LuanFunction)obj;
 		}
 		LuanFunction finallyFn = null;
 		obj = blocks.get(luan,"finally");
 		if( obj != null ) {
 			if( !(obj instanceof LuanFunction) )
-				throw new LuanException(luan,"bad 'finally' value (function expected, got "+Luan.type(obj)+")");
+				throw new LuanException("bad 'finally' value (function expected, got "+Luan.type(obj)+")");
 			finallyFn = (LuanFunction)obj;
 		}
 		try {
@@ -241,8 +244,8 @@
 		}
 	}
 
-	public static String number_type(LuanState luan,Number v) throws LuanException {
-		Utils.checkNotNull(luan,v);
+	public static String number_type(Number v) throws LuanException {
+		Utils.checkNotNull(v);
 		return v.getClass().getSimpleName().toLowerCase();
 	}
 
--- a/core/src/luan/modules/BinaryLuan.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/modules/BinaryLuan.java	Tue Mar 29 19:58:39 2016 -0600
@@ -28,8 +28,8 @@
 		return i==null ? dflt : end(binary,i);
 	}
 
-	@LuanMethod public static Byte[] byte_(LuanState luan,byte[] binary,Integer i,Integer j) throws LuanException {
-		Utils.checkNotNull(luan,binary);
+	@LuanMethod public static Byte[] byte_(byte[] binary,Integer i,Integer j) throws LuanException {
+		Utils.checkNotNull(binary);
 		int start = start(binary,i,1);
 		int end = end(binary,j,start+1);
 		Byte[] bytes = new Byte[end-start];
--- a/core/src/luan/modules/HtmlLuan.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/modules/HtmlLuan.java	Tue Mar 29 19:58:39 2016 -0600
@@ -14,8 +14,8 @@
 
 public final class HtmlLuan {
 
-	public static String encode(LuanState luan,String s) throws LuanException {
-		Utils.checkNotNull(luan,s);
+	public static String encode(String s) throws LuanException {
+		Utils.checkNotNull(s);
 		char[] a = s.toCharArray();
 		StringBuilder buf = new StringBuilder();
 		for( int i=0; i<a.length; i++ ) {
--- a/core/src/luan/modules/IoLuan.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/modules/IoLuan.java	Tue Mar 29 19:58:39 2016 -0600
@@ -122,7 +122,7 @@
 				try {
 					if( args.length > 0 ) {
 						if( args.length > 1 || !"close".equals(args[0]) )
-							throw new LuanException(luan, "the only argument allowed is 'close'" );
+							throw new LuanException( "the only argument allowed is 'close'" );
 						in.close();
 						return null;
 					}
@@ -131,7 +131,7 @@
 						in.close();
 					return rtn;
 				} catch(IOException e) {
-					throw new LuanException(luan,e);
+					throw new LuanException(e);
 				}
 			}
 		};
@@ -145,7 +145,7 @@
 				try {
 					if( args.length > 0 ) {
 						if( args.length > 1 || !"close".equals(args[0]) )
-							throw new LuanException(luan, "the only argument allowed is 'close'" );
+							throw new LuanException( "the only argument allowed is 'close'" );
 						in.close();
 						return null;
 					}
@@ -155,7 +155,7 @@
 					}
 					return a;
 				} catch(IOException e) {
-					throw new LuanException(luan,e);
+					throw new LuanException(e);
 				}
 			}
 		};
@@ -258,7 +258,7 @@
 	public static abstract class LuanIO extends LuanIn {
 		abstract OutputStream outputStream() throws IOException;
 
-		public void write(LuanState luan,Object obj) throws LuanException, IOException {
+		public void write(Object obj) throws LuanException, IOException {
 			if( obj instanceof String ) {
 				String s = (String)obj;
 				Writer out = new OutputStreamWriter(outputStream());
@@ -273,7 +273,7 @@
 				out.close();
 				return;
 			}
-			throw new LuanException(luan, "bad argument #1 to 'write' (string or binary expected)" );
+			throw new LuanException( "bad argument #1 to 'write' (string or binary expected)" );
 		}
 
 		public LuanTable text_writer() throws IOException {
@@ -288,7 +288,7 @@
 			LuanTable tbl = super.table();
 			try {
 				tbl.rawPut( "write", new LuanJavaFunction(
-					LuanIO.class.getMethod( "write", LuanState.class, Object.class ), this
+					LuanIO.class.getMethod( "write", Object.class ), this
 				) );
 				tbl.rawPut( "text_writer", new LuanJavaFunction(
 					LuanIO.class.getMethod( "text_writer" ), this
@@ -516,8 +516,8 @@
 		return nullIO.table();
 	}
 
-	public static LuanTable string(LuanState luan,String s) throws LuanException {
-		Utils.checkNotNull(luan,s);
+	public static LuanTable string(String s) throws LuanException {
+		Utils.checkNotNull(s);
 		return new LuanString(s).table();
 	}
 
@@ -588,10 +588,10 @@
 		LuanTable schemes = new LuanTable();
 		try {
 			schemes.rawPut( "null", new LuanJavaFunction(IoLuan.class.getMethod("null_"),null) );
-			add( schemes, "string", LuanState.class, String.class );
+			add( schemes, "string", String.class );
 			add( schemes, "file", LuanState.class, String.class, Boolean.class );
 			add( schemes, "classpath", LuanState.class, String.class, Boolean.class );
-			add( schemes, "socket", LuanState.class, String.class );
+			add( schemes, "socket", String.class );
 			add( schemes, "http", String.class, Boolean.class );
 			add( schemes, "https", String.class, Boolean.class );
 			add( schemes, "luan", LuanState.class, String.class, Boolean.class );
@@ -615,13 +615,13 @@
 	public static LuanTable uri(LuanState luan,String name,Boolean addExtension) throws LuanException {
 		int i = name.indexOf(':');
 		if( i == -1 )
-			throw new LuanException(luan, "invalid Io.uri name '"+name+"', missing scheme" );
+			throw new LuanException( "invalid Io.uri name '"+name+"', missing scheme" );
 		String scheme = name.substring(0,i);
 		String location = name.substring(i+1);
 		LuanTable schemes = schemes(luan);
 		LuanFunction opener = (LuanFunction)schemes.get(luan,scheme);
 		if( opener == null )
-			throw new LuanException(luan, "invalid scheme '"+scheme+"' in '"+name+"'" );
+			throw new LuanException( "invalid scheme '"+scheme+"' in '"+name+"'" );
 		return (LuanTable)Luan.first(opener.call(luan,new Object[]{location,addExtension}));
 	}
 
@@ -649,10 +649,10 @@
 		}
 	}
 
-	public static LuanTable socket(LuanState luan,String name) throws LuanException, IOException {
+	public static LuanTable socket(String name) throws LuanException, IOException {
 		int i = name.indexOf(':');
 		if( i == -1 )
-			throw new LuanException(luan, "invalid socket '"+name+"', format is: <host>:<port>" );
+			throw new LuanException( "invalid socket '"+name+"', format is: <host>:<port>" );
 		String host = name.substring(0,i);
 		String portStr = name.substring(i+1);
 		int port = Integer.parseInt(portStr);
@@ -666,13 +666,13 @@
 				try {
 					if( args.length > 0 ) {
 						if( args.length > 1 || !"close".equals(args[0]) )
-							throw new LuanException(luan, "the only argument allowed is 'close'" );
+							throw new LuanException( "the only argument allowed is 'close'" );
 						ss.close();
 						return null;
 					}
 					return new LuanSocket(ss.accept()).table();
 				} catch(IOException e) {
-					throw new LuanException(luan,e);
+					throw new LuanException(e);
 				}
 			}
 		};
--- a/core/src/luan/modules/JavaLuan.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/modules/JavaLuan.java	Tue Mar 29 19:58:39 2016 -0600
@@ -42,7 +42,7 @@
 
 	private static void checkJava(LuanState luan) throws LuanException {
 		if( !luan.hasJava() )
-			throw new LuanException(luan,"Java isn't allowed");
+			throw new LuanException("Java isn't allowed");
 	}
 
 	static final Object FAIL = new Object();
@@ -109,7 +109,7 @@
 //System.out.println("invalid member '"+key+"' for java object: "+obj);
 		if( canReturnFail )
 			return FAIL;
-		throw new LuanException(luan, "invalid index for java "+cls );
+		throw new LuanException( "invalid index for java "+cls );
 	}
 
 	private static Object member(Object obj,List<Member> members) throws LuanException {
@@ -176,7 +176,7 @@
 				}
 			}
 		}
-		throw new LuanException(luan, "invalid index for java "+cls );
+		throw new LuanException( "invalid index for java "+cls );
 	}
 
 	private static void setMember(Object obj,List<Member> members,Object value) {
@@ -377,7 +377,7 @@
 					return fn.rawCall(luan,args);
 				} catch(IllegalArgumentException e) {}
 			}
-			throw new LuanException(luan,"no method matched args: "+Arrays.asList(args));
+			throw new LuanException("no method matched args: "+Arrays.asList(args));
 		}
 	}
 
--- a/core/src/luan/modules/PackageLuan.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/modules/PackageLuan.java	Tue Mar 29 19:58:39 2016 -0600
@@ -34,7 +34,7 @@
 	public static Object require(LuanState luan,String modName) throws LuanException {
 		Object mod = load(luan,modName);
 		if( mod==null )
-			throw new LuanException(luan, "module '"+modName+"' not found" );
+			throw new LuanException( "module '"+modName+"' not found" );
 		return mod;
 	}
 
@@ -56,7 +56,7 @@
 					mod = loaded.rawGet(modName);
 					if( mod != null )
 						return mod;
-					throw new LuanException(luan, "module '"+modName+"' returned nil" );
+					throw new LuanException( "module '"+modName+"' returned nil" );
 				}
 			}
 			loaded.rawPut(modName,mod);
--- a/core/src/luan/modules/RpcLuan.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/modules/RpcLuan.java	Tue Mar 29 19:58:39 2016 -0600
@@ -50,7 +50,7 @@
 				return rtn;
 			} else {
 				String msg = readString(in);
-				throw new LuanException(luan,msg);
+				throw new LuanException(msg);
 			}
 		} finally {
 			out.close();
@@ -75,7 +75,7 @@
 				}
 				LuanFunction fn = (LuanFunction)fns.rawGet(fnName);
 				if( fn == null )
-					throw new LuanException(luan, "function not found: " + fnName );
+					throw new LuanException( "function not found: " + fnName );
 				rtn = Luan.array(fn.call(luan,args));
 			} catch(LuanException e) {
 				writeBoolean(out,false);
@@ -121,7 +121,7 @@
 			writeString(out,s);
 		}
 		else
-			throw new LuanException(luan, "invalid type: " + obj.getClass() );
+			throw new LuanException( "invalid type: " + obj.getClass() );
 	}
 
 	static Object readObj(InputStream in,LuanState luan) throws IOException, LuanException {
@@ -142,7 +142,7 @@
 			LuanFunction fn = BasicLuan.load(luan,s,"rpc-reader",null,true);
 			return fn.call(luan);
 		default:
-			throw new LuanException(luan, "invalid type: " + type );
+			throw new LuanException( "invalid type: " + type );
 		}
 	}
 
@@ -208,7 +208,7 @@
 		if( obj instanceof LuanTable ) {
 			LuanTable tbl = (LuanTable)obj;
 			if( !set.add(tbl) ) {
-				throw new LuanException(luan, "circular reference in table" );
+				throw new LuanException( "circular reference in table" );
 			}
 			StringBuilder sb = new StringBuilder();
 			sb.append( "{" );
@@ -222,7 +222,7 @@
 			sb.append( "}" );
 			return sb.toString();
 		}
-		throw new LuanException(luan, "invalid type: " + obj.getClass() );
+		throw new LuanException( "invalid type: " + obj.getClass() );
 	}
 
 }
--- a/core/src/luan/modules/StringLuan.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/modules/StringLuan.java	Tue Mar 29 19:58:39 2016 -0600
@@ -31,8 +31,8 @@
 		return i==null ? dflt : end(s,i);
 	}
 
-	@LuanMethod public static Integer[] unicode(LuanState luan,String s,Integer i,Integer j) throws LuanException {
-		Utils.checkNotNull(luan,s);
+	@LuanMethod public static Integer[] unicode(String s,Integer i,Integer j) throws LuanException {
+		Utils.checkNotNull(s);
 		int start = start(s,i,1);
 		int end = end(s,j,start+1);
 		Integer[] chars = new Integer[end-start];
@@ -54,23 +54,23 @@
 		return s.getBytes();
 	}
 
-	public static String lower(LuanState luan,String s) throws LuanException {
-		Utils.checkNotNull(luan,s);
+	public static String lower(String s) throws LuanException {
+		Utils.checkNotNull(s);
 		return s.toLowerCase();
 	}
 
-	public static String upper(LuanState luan,String s) throws LuanException {
-		Utils.checkNotNull(luan,s);
+	public static String upper(String s) throws LuanException {
+		Utils.checkNotNull(s);
 		return s.toUpperCase();
 	}
 
-	public static String trim(LuanState luan,String s) throws LuanException {
-		Utils.checkNotNull(luan,s);
+	public static String trim(String s) throws LuanException {
+		Utils.checkNotNull(s);
 		return s.trim();
 	}
 
-	public static String reverse(LuanState luan,String s) throws LuanException {
-		Utils.checkNotNull(luan,s);
+	public static String reverse(String s) throws LuanException {
+		Utils.checkNotNull(s);
 		return new StringBuilder(s).reverse().toString();
 	}
 
@@ -86,8 +86,8 @@
 		return buf.toString();
 	}
 
-	public static String sub(LuanState luan,String s,int i,Integer j) throws LuanException {
-		Utils.checkNotNull(luan,s);
+	public static String sub(String s,int i,Integer j) throws LuanException {
+		Utils.checkNotNull(s);
 		int start = start(s,i);
 		int end = end(s,j,s.length());
 		return s.substring(start,end);
@@ -127,8 +127,8 @@
 		return rtn;
 	}
 
-	public static LuanFunction gmatch(LuanState luan,String s,String pattern) throws LuanException {
-		Utils.checkNotNull(luan,s);
+	public static LuanFunction gmatch(String s,String pattern) throws LuanException {
+		Utils.checkNotNull(s);
 		final Matcher m = Pattern.compile(pattern).matcher(s);
 		return new LuanFunction() {
 			@Override public Object call(LuanState luan,Object[] args) {
@@ -147,7 +147,7 @@
 	}
 
 	@LuanMethod public static Object[] gsub(LuanState luan,String s,String pattern,Object repl,Integer n) throws LuanException {
-		Utils.checkNotNull(luan,s);
+		Utils.checkNotNull(s);
 		int max = n==null ? Integer.MAX_VALUE : n;
 		final Matcher m = Pattern.compile(pattern).matcher(s);
 		if( repl instanceof String ) {
@@ -202,7 +202,7 @@
 			m.appendTail(sb);
 			return new Object[]{ sb.toString(), i };
 		}
-		throw new LuanException(luan, "bad argument #3 to 'gsub' (string/function/table expected)" );
+		throw new LuanException( "bad argument #3 to 'gsub' (string/function/table expected)" );
 	}
 
 	// note - String.format() is too stupid to convert between ints and floats.
@@ -222,8 +222,8 @@
 		return Luan.stringEncode(s);
 	}
 
-	public static Number to_number(LuanState luan,String s,Integer base) throws LuanException {
-		Utils.checkNotNull(luan,s);
+	public static Number to_number(String s,Integer base) throws LuanException {
+		Utils.checkNotNull(s);
 		try {
 			if( base == null ) {
 				return Double.valueOf(s);
--- a/core/src/luan/modules/TableLuan.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/modules/TableLuan.java	Tue Mar 29 19:58:39 2016 -0600
@@ -32,16 +32,16 @@
 		return buf.toString();
 	}
 
-	public static void insert(LuanState luan,LuanTable list,int pos,Object value) throws LuanException {
-		Utils.checkNotNull(luan,list);
+	public static void insert(LuanTable list,int pos,Object value) throws LuanException {
+		Utils.checkNotNull(list);
 		if( list.getMetatable() != null )
-			throw new LuanException(luan,"can't insert into a table with a metatable");
+			throw new LuanException("can't insert into a table with a metatable");
 		list.rawInsert(pos,value);
 	}
 
-	public static Object remove(LuanState luan,LuanTable list,int pos) throws LuanException {
+	public static Object remove(LuanTable list,int pos) throws LuanException {
 		if( list.getMetatable() != null )
-			throw new LuanException(luan,"can't remove from a table with a metatable");
+			throw new LuanException("can't remove from a table with a metatable");
 		return list.rawRemove(pos);
 	}
 
@@ -51,7 +51,7 @@
 
 	public static void sort(final LuanState luan,LuanTable list,final LuanFunction comp) throws LuanException {
 		if( list.getMetatable() != null )
-			throw new LuanException(luan,"can't sort a table with a metatable");
+			throw new LuanException("can't sort a table with a metatable");
 		final LessThan lt;
 		if( comp==null ) {
 			lt = new LessThan() {
--- a/core/src/luan/modules/ThreadLuan.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/modules/ThreadLuan.java	Tue Mar 29 19:58:39 2016 -0600
@@ -28,7 +28,7 @@
 	}
 
 	public static LuanFunction synchronized_(final LuanState luan,final LuanFunction fn) throws LuanException {
-		Utils.checkNotNull(luan,fn);
+		Utils.checkNotNull(fn);
 		return new LuanFunction() {
 			@Override public Object call(LuanState ingored,Object[] args) throws LuanException {
 				synchronized(luan) {
--- a/core/src/luan/modules/Utils.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/modules/Utils.java	Tue Mar 29 19:58:39 2016 -0600
@@ -8,7 +8,6 @@
 import java.io.File;
 import java.net.URL;
 import java.net.MalformedURLException;
-import luan.LuanState;
 import luan.LuanException;
 import luan.LuanTable;
 import luan.LuanFunction;
@@ -19,49 +18,49 @@
 
 	static final int bufSize = 8192;
 
-	private static void checkNotNull(LuanState luan,Object v,String expected,int pos) throws LuanException {
+	private static void checkNotNull(Object v,String expected,int pos) throws LuanException {
 		if( v == null )
-			throw new LuanException(luan,"bad argument #"+pos+" ("+expected+" expected, got nil)");
+			throw new LuanException("bad argument #"+pos+" ("+expected+" expected, got nil)");
 	}
 
-	public static void checkNotNull(LuanState luan,String s,int pos) throws LuanException {
-		checkNotNull(luan,s,"string",pos);
+	public static void checkNotNull(String s,int pos) throws LuanException {
+		checkNotNull(s,"string",pos);
 	}
 
-	public static void checkNotNull(LuanState luan,String s) throws LuanException {
-		checkNotNull(luan,s,1);
+	public static void checkNotNull(String s) throws LuanException {
+		checkNotNull(s,1);
 	}
 
-	public static void checkNotNull(LuanState luan,byte[] b,int pos) throws LuanException {
-		checkNotNull(luan,b,"binary",pos);
+	public static void checkNotNull(byte[] b,int pos) throws LuanException {
+		checkNotNull(b,"binary",pos);
 	}
 
-	public static void checkNotNull(LuanState luan,byte[] b) throws LuanException {
-		checkNotNull(luan,b,1);
+	public static void checkNotNull(byte[] b) throws LuanException {
+		checkNotNull(b,1);
 	}
 
-	public static void checkNotNull(LuanState luan,LuanTable t,int pos) throws LuanException {
-		checkNotNull(luan,t,"table",pos);
+	public static void checkNotNull(LuanTable t,int pos) throws LuanException {
+		checkNotNull(t,"table",pos);
 	}
 
-	public static void checkNotNull(LuanState luan,LuanTable t) throws LuanException {
-		checkNotNull(luan,t,1);
+	public static void checkNotNull(LuanTable t) throws LuanException {
+		checkNotNull(t,1);
 	}
 
-	public static void checkNotNull(LuanState luan,Number n,int pos) throws LuanException {
-		checkNotNull(luan,n,"number",pos);
+	public static void checkNotNull(Number n,int pos) throws LuanException {
+		checkNotNull(n,"number",pos);
 	}
 
-	public static void checkNotNull(LuanState luan,Number n) throws LuanException {
-		checkNotNull(luan,n,1);
+	public static void checkNotNull(Number n) throws LuanException {
+		checkNotNull(n,1);
 	}
 
-	public static void checkNotNull(LuanState luan,LuanFunction fn,int pos) throws LuanException {
-		checkNotNull(luan,fn,"function",pos);
+	public static void checkNotNull(LuanFunction fn,int pos) throws LuanException {
+		checkNotNull(fn,"function",pos);
 	}
 
-	public static void checkNotNull(LuanState luan,LuanFunction fn) throws LuanException {
-		checkNotNull(luan,fn,1);
+	public static void checkNotNull(LuanFunction fn) throws LuanException {
+		checkNotNull(fn,1);
 	}
 
 	public static String readAll(Reader in)
--- a/core/src/luan/modules/parsers/BBCode.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/core/src/luan/modules/parsers/BBCode.java	Tue Mar 29 19:58:39 2016 -0600
@@ -25,8 +25,8 @@
 	private final boolean toHtml;
 
 	private BBCode(LuanState luan,String text,LuanFunction quoter,boolean toHtml) throws LuanException {
-		Utils.checkNotNull(luan,text,1);
-		Utils.checkNotNull(luan,quoter,2);
+		Utils.checkNotNull(text,1);
+		Utils.checkNotNull(quoter,2);
 		this.luan = luan;
 		this.parser = new Parser(text);
 		this.quoter = quoter;
@@ -266,7 +266,7 @@
 	private String quote(Object... args) throws LuanException {
 		Object obj = quoter.call(luan,args);
 		if( !(obj instanceof String) )
-			throw new LuanException(luan,"BBCode quoter function returned "+Luan.type(obj)+" but string required");
+			throw new LuanException("BBCode quoter function returned "+Luan.type(obj)+" but string required");
 		return (String)obj;
 	}
 
--- a/http/src/luan/modules/http/HttpServicer.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/http/src/luan/modules/http/HttpServicer.java	Tue Mar 29 19:58:39 2016 -0600
@@ -52,7 +52,7 @@
 			if( mod==null )
 				return false;
 			if( !(mod instanceof LuanFunction) )
-				throw new LuanException(luan, "module '"+modName+"' must return a function" );
+				throw new LuanException( "module '"+modName+"' must return a function" );
 			if( Boolean.TRUE.equals(per_session_pages.rawGet(mod)) ) {
 				HttpSession session = request.getSession();
 				LuanState sessionLuan  = (LuanState)session.getValue("luan");
--- a/lucene/src/luan/modules/lucene/LuceneIndex.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/lucene/src/luan/modules/lucene/LuceneIndex.java	Tue Mar 29 19:58:39 2016 -0600
@@ -115,7 +115,7 @@
 		reader = DirectoryReader.open(dir);
 		luan.onClose(this);
 		searcher = new IndexSearcher(reader);
-		initId(luan);
+		initId();
 	}
 
 
@@ -155,23 +155,23 @@
 		Set indexedOnlySet = new HashSet();
 		Object typeObj = doc.get(luan,"type");
 		if( typeObj==null )
-			throw new LuanException(luan,"missing 'type' field");
+			throw new LuanException("missing 'type' field");
 		if( !(typeObj instanceof String) )
-			throw new LuanException(luan,"type must be string");
+			throw new LuanException("type must be string");
 		String type = (String)typeObj;
 		Object indexedOnlyObj = indexed_only_fields.get(luan,type);
 		if( indexedOnlyObj != null ) {
 			if( !(indexedOnlyObj instanceof LuanTable) )
-				throw new LuanException(luan,"indexed_only_fields elements must be tables");
+				throw new LuanException("indexed_only_fields elements must be tables");
 			LuanTable indexedOnly = (LuanTable)indexedOnlyObj;
 			for( Map.Entry<Object,Object> entry : indexedOnly.iterable(luan) ) {
 				Object key = entry.getKey();
 				if( !(key instanceof String) )
-					throw new LuanException(luan,"indexed_only_fields."+type+" entries must be strings");
+					throw new LuanException("indexed_only_fields."+type+" entries must be strings");
 				String name = (String)key;
 				Object value = entry.getValue();
 				if( !(value instanceof LuanFunction) )
-					throw new LuanException(luan,"indexed_only_fields."+type+" values must be functions");
+					throw new LuanException("indexed_only_fields."+type+" values must be functions");
 				LuanFunction fn = (LuanFunction)value;
 				value = Luan.first(fn.call(luan,new Object[]{doc}));
 				doc.put(luan, name, value );
@@ -183,7 +183,7 @@
 		try {
 			id = (Long)obj;
 		} catch(ClassCastException e) {
-			throw new LuanException(luan,"id should be Long but is "+obj.getClass().getSimpleName());
+			throw new LuanException("id should be Long but is "+obj.getClass().getSimpleName());
 		}
 
 		boolean commit = !writeLock.isHeldByCurrentThread();
@@ -218,7 +218,7 @@
 	private long idLim = 0;
 	private final int idBatch = 10;
 
-	private void initId(LuanState luan) throws LuanException, IOException {
+	private void initId() throws LuanException, IOException {
 		TopDocs td = searcher.search(new TermQuery(new Term("type","next_id")),1);
 /*
 		// tmp hack
@@ -258,9 +258,9 @@
 	}
 
 
-	public void backup(LuanState luan,String zipFile) throws LuanException, IOException {
+	public void backup(String zipFile) throws LuanException, IOException {
 		if( !zipFile.endsWith(".zip") )
-			throw new LuanException(luan,"file "+zipFile+" doesn't end with '.zip'");
+			throw new LuanException("file "+zipFile+" doesn't end with '.zip'");
 		IndexCommit ic = snapshotDeletionPolicy.snapshot();
 		try {
 			ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));
@@ -311,9 +311,9 @@
 
 		@Override public Object call(LuanState luan,Object[] args) throws LuanException {
 			try {
-				return toTable(luan,searcher.doc(docID));
+				return toTable(searcher.doc(docID));
 			} catch(IOException e) {
-				throw new LuanException(luan,e);
+				throw new LuanException(e);
 			}
 		}
 	}
@@ -352,7 +352,7 @@
 	}
 
 	public int advanced_search( final LuanState luan, String queryStr, LuanFunction fn, Integer n, String sortStr ) throws LuanException, IOException, ParseException {
-		Utils.checkNotNull(luan,queryStr);
+		Utils.checkNotNull(queryStr);
 		Query query = SaneQueryParser.parseQuery(mfp,queryStr);
 		IndexSearcher searcher = threadLocalSearcher.get();
 		boolean inTransaction = searcher != null;
@@ -361,7 +361,7 @@
 		try {
 			if( fn!=null && n==null ) {
 				if( sortStr != null )
-					throw new LuanException(luan,"sort must be nil when n is nil");
+					throw new LuanException("sort must be nil when n is nil");
 				final DocFn docFn = new DocFn(searcher);
 				MyCollector col = new MyCollector() {
 					@Override public void collect(int doc) {
@@ -402,7 +402,7 @@
 
 	public Object search_in_transaction(LuanState luan,LuanFunction fn) throws LuanException, IOException {
 		if( threadLocalSearcher.get() != null )
-			throw new LuanException(luan,"can't nest search_in_transaction calls");
+			throw new LuanException("can't nest search_in_transaction calls");
 		IndexSearcher searcher = openSearcher();
 		threadLocalSearcher.set(searcher);
 		try {
@@ -427,14 +427,14 @@
 
 		@Override public void __new_index(LuanState luan,LuanTable tbl,Object key,Object value) throws LuanException {
 			if( !(key instanceof String) )
-				throw new LuanException(luan,"key must be string");
+				throw new LuanException("key must be string");
 			String field = (String)key;
 			if( value==null ) {  // delete
 				mfp.fields.remove(field);
 				return;
 			}
 			if( !(value instanceof FieldParser) )
-				throw new LuanException(luan,"value must be FieldParser like the values of Lucene.type");
+				throw new LuanException("value must be FieldParser like the values of Lucene.type");
 			FieldParser parser = (FieldParser)value;
 			mfp.fields.put( field, parser );
 		}
@@ -451,7 +451,7 @@
 
 
 
-	private IndexableField newField(LuanState luan,String name,Object value,Field.Store store,Set<String> indexed)
+	private IndexableField newField(String name,Object value,Field.Store store,Set<String> indexed)
 		throws LuanException
 	{
 		if( value instanceof String ) {
@@ -491,7 +491,7 @@
 			byte[] b = (byte[])value;
 			return new StoredField(name, b);
 		} else
-			throw new LuanException(luan,"invalid value type "+value.getClass()+"' for '"+name+"'");
+			throw new LuanException("invalid value type "+value.getClass()+"' for '"+name+"'");
 	}
 
 	private Document toLucene(LuanState luan,LuanTable table,Set indexOnly) throws LuanException {
@@ -500,23 +500,23 @@
 		for( Map.Entry<Object,Object> entry : table.iterable(luan) ) {
 			Object key = entry.getKey();
 			if( !(key instanceof String) )
-				throw new LuanException(luan,"key must be string");
+				throw new LuanException("key must be string");
 			String name = (String)key;
 			Object value = entry.getValue();
 			Field.Store store = indexOnly.contains(name) ? Field.Store.NO : Field.Store.YES;
 			if( !(value instanceof LuanTable) ) {
-				doc.add(newField(luan, name, value, store, indexed));
+				doc.add(newField(name, value, store, indexed));
 			} else { // list
 				LuanTable list = (LuanTable)value;
 				for( Object el : list.asList() ) {
-					doc.add(newField(luan, name, el, store, indexed));
+					doc.add(newField(name, el, store, indexed));
 				}
 			}
 		}
 		return doc;
 	}
 
-	private static Object getValue(LuanState luan,IndexableField ifld) throws LuanException {
+	private static Object getValue(IndexableField ifld) throws LuanException {
 		BytesRef br = ifld.binaryValue();
 		if( br != null )
 			return br.bytes;
@@ -526,16 +526,16 @@
 		String s = ifld.stringValue();
 		if( s != null )
 			return s;
-		throw new LuanException(luan,"invalid field type for "+ifld);
+		throw new LuanException("invalid field type for "+ifld);
 	}
 
-	private static LuanTable toTable(LuanState luan,Document doc) throws LuanException {
+	private static LuanTable toTable(Document doc) throws LuanException {
 		if( doc==null )
 			return null;
 		LuanTable table = new LuanTable();
 		for( IndexableField ifld : doc ) {
 			String name = ifld.name();
-			Object value = getValue(luan,ifld);
+			Object value = getValue(ifld);
 			Object old = table.rawGet(name);
 			if( old == null ) {
 				table.rawPut(name,value);
--- a/mail/src/luan/modules/mail/SmtpCon.java	Tue Mar 29 18:09:51 2016 -0600
+++ b/mail/src/luan/modules/mail/SmtpCon.java	Tue Mar 29 19:58:39 2016 -0600
@@ -28,9 +28,9 @@
 		Map<Object,Object> params = new HashMap<Object,Object>(paramsTbl.asMap(luan));
 		Properties props = new Properties(System.getProperties());
 
-		String host = getString(luan,params,"host");
+		String host = getString(params,"host");
 		if( host==null )
-			throw new LuanException(luan, "parameter 'host' is required" );
+			throw new LuanException( "parameter 'host' is required" );
 		props.setProperty("mail.smtp.host",host);
 
 		Object port = params.remove("port");
@@ -41,22 +41,22 @@
 			} else if( port instanceof Number ) {
 				Integer i = Luan.asInteger(port);
 				if( i == null )
-					throw new LuanException(luan, "parameter 'port' must be an integer" );
+					throw new LuanException( "parameter 'port' must be an integer" );
 				s = i.toString();
 			} else {
-				throw new LuanException(luan, "parameter 'port' must be an integer" );
+				throw new LuanException( "parameter 'port' must be an integer" );
 			}
 			props.setProperty("mail.smtp.socketFactory.port", s);
 			props.setProperty("mail.smtp.port", s);
 		}
 
-		String username = getString(luan,params,"username");
+		String username = getString(params,"username");
 		if( username == null ) {
 			session = Session.getInstance(props);
 		} else {
-			String password = getString(luan,params,"password");
+			String password = getString(params,"password");
 			if( password==null )
-				throw new LuanException(luan, "parameter 'password' is required with 'username'" );
+				throw new LuanException( "parameter 'password' is required with 'username'" );
 			props.setProperty("mail.smtp.auth","true");
 			final PasswordAuthentication pa = new PasswordAuthentication(username,password);
 			Authenticator auth = new Authenticator() {
@@ -68,13 +68,13 @@
 		}
 
 		if( !params.isEmpty() )
-			throw new LuanException(luan, "unrecognized parameters: "+params );
+			throw new LuanException( "unrecognized parameters: "+params );
 	}
 
-	private String getString(LuanState luan,Map<Object,Object> params,String key) throws LuanException {
+	private String getString(Map<Object,Object> params,String key) throws LuanException {
 		Object val = params.remove(key);
 		if( val!=null && !(val instanceof String) )
-			throw new LuanException(luan, "parameter '"+key+"' must be a string" );
+			throw new LuanException( "parameter '"+key+"' must be a string" );
 		return (String)val;
 	}
 
@@ -84,19 +84,19 @@
 			Map<Object,Object> mailParams = new HashMap<Object,Object>(mailTbl.asMap(luan));
 			MimeMessage msg = new MimeMessage(session);
 
-			String from = getString(luan,mailParams,"from");
+			String from = getString(mailParams,"from");
 			if( from != null )
 				msg.setFrom(from);
 
-			String to = getString(luan,mailParams,"to");
+			String to = getString(mailParams,"to");
 			if( to != null )
 				msg.setRecipients(Message.RecipientType.TO,to);
 
-			String cc = getString(luan,mailParams,"cc");
+			String cc = getString(mailParams,"cc");
 			if( cc != null )
 				msg.setRecipients(Message.RecipientType.CC,cc);
 
-			String subject = getString(luan,mailParams,"subject");
+			String subject = getString(mailParams,"subject");
 			if( subject != null )
 				msg.setSubject(subject);
 
@@ -124,49 +124,49 @@
 						mp.addBodyPart(part);
 					}
 					if( !map.isEmpty() )
-						throw new LuanException(luan, "invalid body types: " + map );
+						throw new LuanException( "invalid body types: " + map );
 					bodyPart.setContent(mp);
 				} else
-					throw new LuanException(luan, "parameter 'body' must be a string or table" );
+					throw new LuanException( "parameter 'body' must be a string or table" );
 			}
 
 			if( attachments != null ) {
 				if( !(attachments instanceof LuanTable) )
-					throw new LuanException(luan, "parameter 'attachments' must be a table" );
+					throw new LuanException( "parameter 'attachments' must be a table" );
 				LuanTable attachmentsTbl = (LuanTable)attachments;
 				if( !attachmentsTbl.isList() )
-					throw new LuanException(luan, "parameter 'attachments' must be a list" );
+					throw new LuanException( "parameter 'attachments' must be a list" );
 				MimeMultipart mp = new MimeMultipart("mixed");
 				if( body != null )
 					mp.addBodyPart((MimeBodyPart)bodyPart);
 				for( Object attachment : attachmentsTbl.asList() ) {
 					if( !(attachment instanceof LuanTable) )
-						throw new LuanException(luan, "each attachment must be a table" );
+						throw new LuanException( "each attachment must be a table" );
 					Map<Object,Object> attachmentMap = new HashMap<Object,Object>(((LuanTable)attachment).asMap(luan));
 					Object obj;
 
 					obj = attachmentMap.remove("filename");
 					if( obj==null )
-						throw new LuanException(luan, "an attachment is missing 'filename'" );
+						throw new LuanException( "an attachment is missing 'filename'" );
 					if( !(obj instanceof String) )
-						throw new LuanException(luan, "an attachment filename must be a string" );
+						throw new LuanException( "an attachment filename must be a string" );
 					String filename = (String)obj;
 
 					obj = attachmentMap.remove("content_type");
 					if( obj==null )
-						throw new LuanException(luan, "an attachment is missing 'content_type'" );
+						throw new LuanException( "an attachment is missing 'content_type'" );
 					if( !(obj instanceof String) )
-						throw new LuanException(luan, "an attachment content_type must be a string" );
+						throw new LuanException( "an attachment content_type must be a string" );
 					String content_type = (String)obj;
 
 					Object content = attachmentMap.remove("content");
 					if( content==null )
-						throw new LuanException(luan, "an attachment is missing 'content'" );
+						throw new LuanException( "an attachment is missing 'content'" );
 					if( content_type.startsWith("text/") && content instanceof byte[] )
 						content = new String((byte[])content);
 
 					if( !attachmentMap.isEmpty() )
-						throw new LuanException(luan, "unrecognized attachment parameters: "+attachmentMap );
+						throw new LuanException( "unrecognized attachment parameters: "+attachmentMap );
 
 					MimeBodyPart part = new MimeBodyPart();
 					part.setContent(content,content_type);
@@ -177,11 +177,11 @@
 			}
 
 			if( !mailParams.isEmpty() )
-				throw new LuanException(luan, "unrecognized parameters: "+mailParams );
+				throw new LuanException( "unrecognized parameters: "+mailParams );
 
 			Transport.send(msg);
 		} catch(MessagingException e) {
-			throw new LuanException(luan,e);
+			throw new LuanException(e);
 		}
 	}