changeset 1333:25746915a241

merge Luan and LuanState
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 12 Feb 2019 22:33:40 -0700
parents 11b7e11f9ed5
children c88b486a9511
files conv.txt src/luan/Luan.java src/luan/LuanClosure.java src/luan/LuanException.java src/luan/LuanFunction.java src/luan/LuanJavaFunction.java src/luan/LuanState.java src/luan/LuanTable.java src/luan/host/Backup.java src/luan/host/WebHandler.java src/luan/impl/LuanCompiler.java src/luan/impl/LuanImpl.java src/luan/impl/LuanParser.java src/luan/modules/BasicLuan.java src/luan/modules/BinaryLuan.java src/luan/modules/HtmlLuan.java src/luan/modules/IoLuan.java src/luan/modules/JavaLuan.java src/luan/modules/MathLuan.java src/luan/modules/PackageLuan.java src/luan/modules/StringLuan.java src/luan/modules/TableLuan.java src/luan/modules/ThreadLuan.java src/luan/modules/http/HttpServicer.java src/luan/modules/http/LuanDomainHandler.java src/luan/modules/http/LuanHandler.java src/luan/modules/logging/Log4j.java src/luan/modules/logging/LuanLogger.java src/luan/modules/lucene/LuceneIndex.java src/luan/modules/mail/SmtpCon.java src/luan/modules/parsers/BBCode.java src/luan/modules/parsers/Css.java src/luan/modules/parsers/Csv.java src/luan/modules/parsers/Html.java src/luan/modules/sql/Database.java src/luan/modules/url/LuanUrl.java
diffstat 36 files changed, 398 insertions(+), 499 deletions(-) [+]
line wrap: on
line diff
--- a/conv.txt	Tue Feb 12 21:50:26 2019 -0700
+++ b/conv.txt	Tue Feb 12 22:33:40 2019 -0700
@@ -1,3 +1,4 @@
+LuanState
 LuanLogger
 
 file - java.*
--- a/src/luan/Luan.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/Luan.java	Tue Feb 12 22:33:40 2019 -0700
@@ -1,25 +1,185 @@
 package luan;
 
+import java.lang.reflect.Array;
+import java.io.Closeable;
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Map;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
-import java.util.Set;
+import java.util.Iterator;
 import java.util.Arrays;
-import java.util.Iterator;
+import java.util.Set;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import luan.modules.BasicLuan;
-import luan.modules.Utils;
+import luan.modules.JavaLuan;
+import luan.modules.PackageLuan;
 import luan.impl.LuanCompiler;
 
 
-public final class Luan {
+public final class Luan implements LuanCloneable {
+	private static final Logger logger = LoggerFactory.getLogger(Luan.class);
+
+	private final List<LuanClosure> stack = new ArrayList<LuanClosure>();
+	private Map registry;
+	public boolean isLocked = false;
+
+	public interface OnClose extends Closeable {
+		public void onClose(Closeable c);
+	}
+	public OnClose onClose;
+
+	public Luan() {
+		registry = new HashMap();
+	}
+
+	private Luan(Luan luan) {}
+
+	@Override public Luan shallowClone() {
+		return new Luan(this);
+	}
+
+	@Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) {
+		Luan clone = (Luan)dc;
+		clone.registry = cloner.clone(registry);
+		if( cloner.type == LuanCloner.Type.INCREMENTAL )
+			isLocked = true;
+	}
+
+	public LuanClosure peek() {
+		return peek(1);
+	}
+
+	public LuanClosure peek(int i) {
+		int n = stack.size();
+		return n < i ? null : stack.get(n-i);
+	}
+
+	void push(LuanClosure closure) {
+		stack.add(closure);
+	}
+
+	void pop() {
+		stack.remove(stack.size()-1);
+	}
+
+	public Map registry() {
+		return registry;
+	}
+
+	public void onClose(Closeable c) {
+		if( onClose != null )
+			onClose.onClose(c);
+	}
+
+	public Object eval(String cmd,Object... args) throws LuanException {
+		return Luan.load(cmd,"eval").call(this,args);
+	}
+
+	public Object require(String modName) throws LuanException {
+		return PackageLuan.require(this,modName);
+	}
+
+	public String toString(Object obj) throws LuanException {
+		if( obj instanceof LuanTable ) {
+			LuanTable tbl = (LuanTable)obj;
+			return tbl.toStringLuan();
+		}
+		if( obj == null )
+			return "nil";
+		if( obj instanceof Number )
+			return Luan.toString((Number)obj);
+		if( obj instanceof byte[] )
+			return "binary: " + Integer.toHexString(obj.hashCode());
+		return obj.toString();
+	}
+
+	public Object index(Object obj,Object key) throws LuanException {
+		if( obj instanceof LuanTable ) {
+			LuanTable tbl = (LuanTable)obj;
+			return tbl.get(key);
+		}
+		if( obj != null && peek().javaOk )
+			return JavaLuan.__index(this,obj,key);
+		throw new LuanException("attempt to index a " + Luan.type(obj) + " value" );
+	}
+
+
+	public boolean isLessThan(Object o1,Object o2) throws LuanException {
+		if( o1 instanceof Number && o2 instanceof Number ) {
+			Number n1 = (Number)o1;
+			Number n2 = (Number)o2;
+			return n1.doubleValue() < n2.doubleValue();
+		}
+		if( o1 instanceof String && o2 instanceof String ) {
+			String s1 = (String)o1;
+			String s2 = (String)o2;
+			return s1.compareTo(s2) < 0;
+		}
+		LuanFunction fn = getBinHandler("__lt",o1,o2);
+		if( fn != null )
+			return Luan.checkBoolean( Luan.first(fn.call(this,new Object[]{o1,o2})) );
+		throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) );
+	}
+
+	public LuanFunction getBinHandler(String op,Object o1,Object o2) throws LuanException {
+		if( o1 instanceof LuanTable ) {
+			LuanFunction f1 = getHandlerFunction(op,(LuanTable)o1);
+			if( f1 != null )
+				return f1;
+		}
+		return o2 instanceof LuanTable ? getHandlerFunction(op,(LuanTable)o2) : null;
+	}
+
+	public LuanFunction getHandlerFunction(String op,LuanTable t) throws LuanException {
+		Object f = t.getHandler(op);
+		if( f == null )
+			return null;
+		return Luan.checkFunction(f);
+	}
+
+	public LuanTable toTable(Object obj) {
+		if( obj == null )
+			return null;
+		if( obj instanceof LuanTable )
+			return (LuanTable)obj;
+		if( obj instanceof List ) {
+			return new LuanTable(this,(List)obj);
+		}
+		if( obj instanceof Map ) {
+			return new LuanTable(this,(Map)obj);
+		}
+		if( obj instanceof Set ) {
+			return new LuanTable(this,(Set)obj);
+		}
+		Class cls = obj.getClass();
+		if( cls.isArray() ) {
+			if( cls.getComponentType().isPrimitive() ) {
+				int len = Array.getLength(obj);
+				List list = new ArrayList();
+				for( int i=0; i<len; i++ ) {
+					list.add(Array.get(obj,i));
+				}
+				return new LuanTable(this,list);
+			} else {
+				Object[] a = (Object[])obj;
+				return new LuanTable(this,Arrays.asList(a));
+			}
+		}
+		return null;
+	}
+
+
+
+	// static
 
 	public static void main(String[] args) throws LuanException {
 		doFile( "classpath:luan/cmd_line.luan", args );
 	}
 
 	public static void doFile(String uri,String... args) throws LuanException {
-		LuanState luan = new LuanState();
+		Luan luan = new Luan();
 		LuanFunction fn = (LuanFunction)BasicLuan.load_file(luan,uri);
 		fn.call(luan,args);
 	}
@@ -98,8 +258,6 @@
 	}
 
 
-	// from LuanState
-
 	public static Boolean checkBoolean(Object obj) throws LuanException {
 		if( obj instanceof Boolean )
 			return (Boolean)obj;
@@ -130,51 +288,6 @@
 		return load(text,sourceName,null);
 	}
 
-/*
-	public static Object toLuan(Object obj) throws LuanException {
-		if( !type(obj).equals("java") )
-			return obj;
-		LuanTable tbl = new LuanTable();
-		if( obj instanceof Map ) {
-			Map map = (Map)obj;
-			for( Object stupid : map.entrySet() ) {
-				Map.Entry entry = (Map.Entry)stupid;
-				Object key = entry.getKey();
-				Object value = entry.getValue();
-				if( key != null && value != null )
-					tbl.rawPut(toLuan(key),toLuan(value));
-			}
-			return tbl;
-		}
-		if( obj instanceof Set ) {
-			Set set = (Set)obj;
-			for( Object el : set ) {
-				if( el != null )
-					tbl.rawPut(toLuan(el),Boolean.TRUE);
-			}
-			return tbl;
-		}
-		List list;
-		if( obj instanceof List ) {
-			list = (List)obj;
-		} else {
-			Class cls = obj.getClass();
-			if( cls.isArray() && !cls.getComponentType().isPrimitive() ) {
-				Object[] a = (Object[])obj;
-				list = Arrays.asList(a);
-			} else
-				throw new LuanException("can't convert type "+obj.getClass().getName()+" to luan");
-		}
-		int n = list.size();
-		for( int i=0; i<n; i++ ) {
-			Object val = list.get(i);
-			if( val != null )
-				tbl.rawPut(i+1,toLuan(val));
-		}
-		return tbl;
-	}
-*/
-
 	public static Object toJava(Object obj) throws LuanException {
 		if( !(obj instanceof LuanTable) )
 			return obj;
@@ -195,41 +308,32 @@
 			return map;
 		}
 	}
-/*
-	public static LuanTable table(LuanTable v) throws LuanException {
-		Utils.checkNotNull(v);
-		return v;
-	}
-*/
-
 
 
 	// security
 
 	public interface Security {
-		public void check(LuanState luan,LuanClosure closure,String op,Object... args) throws LuanException;
+		public void check(Luan luan,LuanClosure closure,String op,Object... args) throws LuanException;
 	}
 
 	private static String SECURITY_KEY = "Luan.Security";
 
-	public static void checkSecurity(LuanState luan,String op,Object... args) throws LuanException {
+	public static void checkSecurity(Luan luan,String op,Object... args) throws LuanException {
 		check(luan,1,op,args);
 	}
 
-	public static void checkCallerSecurity(LuanState luan,String op,Object... args) throws LuanException {
+	public static void checkCallerSecurity(Luan luan,String op,Object... args) throws LuanException {
 		check(luan,2,op,args);
 	}
 
-	private static void check(LuanState luan,int i,String op,Object... args) throws LuanException {
+	private static void check(Luan luan,int i,String op,Object... args) throws LuanException {
 		Security s = (Security)luan.registry().get(SECURITY_KEY);
 		if( s!=null )
 			s.check(luan,luan.peek(),op,args);
 	}
 
-	public static Security setSecurity(LuanState luan,Security s) {
+	public static Security setSecurity(Luan luan,Security s) {
 		return (Security)luan.registry().put(SECURITY_KEY,s);
 	}
 
-
-	private Luan() {}  // never
 }
--- a/src/luan/LuanClosure.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/LuanClosure.java	Tue Feb 12 22:33:40 2019 -0700
@@ -44,7 +44,7 @@
 		}
 	}
 
-	@Override public final Object call(LuanState luan,Object[] args) throws LuanException {
+	@Override public final Object call(Luan luan,Object[] args) throws LuanException {
 		if( luan.isLocked )
 			throw new RuntimeException("luan is locked");
 		check();
@@ -58,5 +58,5 @@
 		}	
 	}
 
-	public abstract Object doCall(LuanState luan,Object[] args) throws LuanException;
+	public abstract Object doCall(Luan luan,Object[] args) throws LuanException;
 }
--- a/src/luan/LuanException.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/LuanException.java	Tue Feb 12 22:33:40 2019 -0700
@@ -31,7 +31,7 @@
 		clone.table = (LuanTable)cloner.clone(table);
 	}
 
-	public LuanTable table(LuanState luan) {
+	public LuanTable table(Luan luan) {
 		if( table==null ) {
 			try {
 				LuanTable Boot = (LuanTable)luan.require("luan:Boot.luan");
--- a/src/luan/LuanFunction.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/LuanFunction.java	Tue Feb 12 22:33:40 2019 -0700
@@ -3,11 +3,11 @@
 
 public abstract class LuanFunction {
 
-	public abstract Object call(LuanState luan,Object[] args) throws LuanException;
+	public abstract Object call(Luan luan,Object[] args) throws LuanException;
 
 	public static final Object[] NOTHING = new Object[0];
 
-	public final Object call(LuanState luan) throws LuanException {
+	public final Object call(Luan luan) throws LuanException {
 		return call(luan,NOTHING);
 	}
 
--- a/src/luan/LuanJavaFunction.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/LuanJavaFunction.java	Tue Feb 12 22:33:40 2019 -0700
@@ -55,7 +55,7 @@
 		return method.isVarArgs();
 	}
 
-	@Override public Object call(LuanState luan,Object[] args) throws LuanException {
+	@Override public Object call(Luan luan,Object[] args) throws LuanException {
 		try {
 			args = fixArgs(luan,args);
 			return doCall(luan,args);
@@ -65,12 +65,12 @@
 		}
 	}
 
-	public Object rawCall(LuanState luan,Object[] args) throws LuanException {
+	public Object rawCall(Luan 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(Luan luan,Object[] args) throws LuanException {
 		Object rtn;
 		try {
 			rtn = method.invoke(obj,args);
@@ -146,7 +146,7 @@
 		return type;
 	}
 
-	private Object[] fixArgs(LuanState luan,Object[] args) throws LuanException {
+	private Object[] fixArgs(Luan luan,Object[] args) throws LuanException {
 		int n = argConverters.length;
 		Object[] rtn;
 		int start = 0;
@@ -189,23 +189,23 @@
 
 
 	private interface RtnConverter {
-		public Object convert(LuanState luan,Object obj);
+		public Object convert(Luan luan,Object obj);
 	}
 
 	private static final RtnConverter RTN_NOTHING = new RtnConverter() {
-		@Override public Object[] convert(LuanState luan,Object obj) {
+		@Override public Object[] convert(Luan luan,Object obj) {
 			return NOTHING;
 		}
 	};
 
 	private static final RtnConverter RTN_SAME = new RtnConverter() {
-		@Override public Object convert(LuanState luan,Object obj) {
+		@Override public Object convert(Luan luan,Object obj) {
 			return obj;
 		}
 	};
 
 	private static final RtnConverter RTN_ARRAY = new RtnConverter() {
-		@Override public Object convert(LuanState luan,Object obj) {
+		@Override public Object convert(Luan luan,Object obj) {
 			if( obj == null )
 				return null;
 			Object[] a = new Object[Array.getLength(obj)];
@@ -227,11 +227,11 @@
 	}
 
 	private interface ArgConverter {
-		public Object convert(LuanState luan,Object obj) throws LuanException;
+		public Object convert(Luan luan,Object obj) throws LuanException;
 	}
 
 	private static final ArgConverter ARG_SAME = new ArgConverter() {
-		public Object convert(LuanState luan,Object obj) {
+		public Object convert(Luan luan,Object obj) {
 			return obj;
 		}
 		@Override public String toString() {
@@ -240,7 +240,7 @@
 	};
 
 	private static final ArgConverter ARG_DOUBLE = new ArgConverter() {
-		public Object convert(LuanState luan,Object obj) {
+		public Object convert(Luan luan,Object obj) {
 			if( obj instanceof Double )
 				return obj;
 			if( obj instanceof Number ) {
@@ -255,7 +255,7 @@
 	};
 
 	private static final ArgConverter ARG_FLOAT = new ArgConverter() {
-		public Object convert(LuanState luan,Object obj) {
+		public Object convert(Luan luan,Object obj) {
 			if( obj instanceof Float )
 				return obj;
 			if( obj instanceof Number ) {
@@ -270,7 +270,7 @@
 	};
 
 	private static final ArgConverter ARG_LONG = new ArgConverter() {
-		public Object convert(LuanState luan,Object obj) {
+		public Object convert(Luan luan,Object obj) {
 			if( obj instanceof Long )
 				return obj;
 			if( obj instanceof Number ) {
@@ -287,7 +287,7 @@
 	};
 
 	private static final ArgConverter ARG_INTEGER = new ArgConverter() {
-		public Object convert(LuanState luan,Object obj) {
+		public Object convert(Luan luan,Object obj) {
 			if( obj instanceof Integer )
 				return obj;
 			if( obj instanceof Number ) {
@@ -304,7 +304,7 @@
 	};
 
 	private static final ArgConverter ARG_SHORT = new ArgConverter() {
-		public Object convert(LuanState luan,Object obj) {
+		public Object convert(Luan luan,Object obj) {
 			if( obj instanceof Short )
 				return obj;
 			if( obj instanceof Number ) {
@@ -321,7 +321,7 @@
 	};
 
 	private static final ArgConverter ARG_BYTE = new ArgConverter() {
-		public Object convert(LuanState luan,Object obj) {
+		public Object convert(Luan luan,Object obj) {
 			if( obj instanceof Byte )
 				return obj;
 			if( obj instanceof Number ) {
@@ -338,7 +338,7 @@
 	};
 
 	private static final ArgConverter ARG_TABLE = new ArgConverter() {
-		public Object convert(LuanState luan,Object obj) {
+		public Object convert(Luan luan,Object obj) {
 			LuanTable tbl = luan.toTable(obj);
 			return tbl!=null ? tbl : obj;
 		}
@@ -348,7 +348,7 @@
 	};
 
 	private static final ArgConverter ARG_MAP = new ArgConverter() {
-		public Object convert(LuanState luan,Object obj) throws LuanException {
+		public Object convert(Luan luan,Object obj) throws LuanException {
 			if( obj instanceof LuanTable ) {
 				LuanTable t = (LuanTable)obj;
 				return t.asMap();
@@ -361,7 +361,7 @@
 	};
 
 	private static final ArgConverter ARG_LIST = new ArgConverter() {
-		public Object convert(LuanState luan,Object obj) {
+		public Object convert(Luan luan,Object obj) {
 			if( obj instanceof LuanTable ) {
 				LuanTable t = (LuanTable)obj;
 				if( t.isList() )
@@ -375,7 +375,7 @@
 	};
 
 	private static final ArgConverter ARG_SET = new ArgConverter() {
-		public Object convert(LuanState luan,Object obj) throws LuanException {
+		public Object convert(Luan luan,Object obj) throws LuanException {
 			if( obj instanceof LuanTable ) {
 				LuanTable t = (LuanTable)obj;
 				if( t.isSet() )
@@ -389,7 +389,7 @@
 	};
 
 	private static final ArgConverter ARG_COLLECTION = new ArgConverter() {
-		public Object convert(LuanState luan,Object obj) throws LuanException {
+		public Object convert(Luan luan,Object obj) throws LuanException {
 			if( obj instanceof LuanTable ) {
 				LuanTable t = (LuanTable)obj;
 				if( t.isList() )
@@ -411,7 +411,7 @@
 			a = (Object[])Array.newInstance(cls.getComponentType(),0);
 		}
 
-		public Object convert(LuanState luan,Object obj) {
+		public Object convert(Luan luan,Object obj) {
 			if( obj instanceof LuanTable ) {
 				LuanTable t = (LuanTable)obj;
 				if( t.isList() ) {
@@ -426,7 +426,7 @@
 
 	private static boolean takesLuaState(JavaMethod m) {
 		Class[] paramTypes = m.getParameterTypes();
-		return paramTypes.length > 0 && paramTypes[0].equals(LuanState.class);
+		return paramTypes.length > 0 && paramTypes[0].equals(Luan.class);
 	}
 
 	private static ArgConverter[] getArgConverters(boolean takesLuaState,JavaMethod m) {
--- a/src/luan/LuanState.java	Tue Feb 12 21:50:26 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,180 +0,0 @@
-package luan;
-
-import java.lang.reflect.Array;
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Set;
-import java.util.Arrays;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import luan.impl.LuanCompiler;
-import luan.modules.BasicLuan;
-import luan.modules.JavaLuan;
-import luan.modules.PackageLuan;
-
-
-public final class LuanState implements LuanCloneable {
-	private static final Logger logger = LoggerFactory.getLogger(LuanState.class);
-
-	private final List<LuanClosure> stack = new ArrayList<LuanClosure>();
-	private Map registry;
-	public boolean isLocked = false;
-
-	public interface OnClose extends Closeable {
-		public void onClose(Closeable c);
-	}
-	public OnClose onClose;
-
-	public LuanState() {
-		registry = new HashMap();
-	}
-
-	private LuanState(LuanState luan) {}
-
-	@Override public LuanState shallowClone() {
-		return new LuanState(this);
-	}
-
-	@Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) {
-		LuanState clone = (LuanState)dc;
-		clone.registry = cloner.clone(registry);
-		if( cloner.type == LuanCloner.Type.INCREMENTAL )
-			isLocked = true;
-	}
-
-	public LuanClosure peek() {
-		return peek(1);
-	}
-
-	public LuanClosure peek(int i) {
-		int n = stack.size();
-		return n < i ? null : stack.get(n-i);
-	}
-
-	void push(LuanClosure closure) {
-		stack.add(closure);
-	}
-
-	void pop() {
-		stack.remove(stack.size()-1);
-	}
-
-	public Map registry() {
-		return registry;
-	}
-
-	public void onClose(Closeable c) {
-		if( onClose != null )
-			onClose.onClose(c);
-	}
-
-	public Object eval(String cmd,Object... args) throws LuanException {
-		return Luan.load(cmd,"eval").call(this,args);
-	}
-
-	public Object require(String modName) throws LuanException {
-		return PackageLuan.require(this,modName);
-	}
-
-	public String toString(Object obj) throws LuanException {
-		if( obj instanceof LuanTable ) {
-			LuanTable tbl = (LuanTable)obj;
-			return tbl.toStringLuan();
-		}
-		if( obj == null )
-			return "nil";
-		if( obj instanceof Number )
-			return Luan.toString((Number)obj);
-		if( obj instanceof byte[] )
-			return "binary: " + Integer.toHexString(obj.hashCode());
-		return obj.toString();
-	}
-
-	public Object index(Object obj,Object key) throws LuanException {
-		if( obj instanceof LuanTable ) {
-			LuanTable tbl = (LuanTable)obj;
-			return tbl.get(key);
-		}
-		if( obj != null && peek().javaOk )
-			return JavaLuan.__index(this,obj,key);
-		throw new LuanException("attempt to index a " + Luan.type(obj) + " value" );
-	}
-
-/*
-	public Number checkNumber(Object obj) throws LuanException {
-		if( obj instanceof Number )
-			return (Number)obj;
-		throw new LuanException( "attempt to perform arithmetic on '"+context()+"' (a " + Luan.type(obj) + " value)" );
-	}
-*/
-
-
-	public boolean isLessThan(Object o1,Object o2) throws LuanException {
-		if( o1 instanceof Number && o2 instanceof Number ) {
-			Number n1 = (Number)o1;
-			Number n2 = (Number)o2;
-			return n1.doubleValue() < n2.doubleValue();
-		}
-		if( o1 instanceof String && o2 instanceof String ) {
-			String s1 = (String)o1;
-			String s2 = (String)o2;
-			return s1.compareTo(s2) < 0;
-		}
-		LuanFunction fn = getBinHandler("__lt",o1,o2);
-		if( fn != null )
-			return Luan.checkBoolean( Luan.first(fn.call(this,new Object[]{o1,o2})) );
-		throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) );
-	}
-
-	public LuanFunction getBinHandler(String op,Object o1,Object o2) throws LuanException {
-		if( o1 instanceof LuanTable ) {
-			LuanFunction f1 = getHandlerFunction(op,(LuanTable)o1);
-			if( f1 != null )
-				return f1;
-		}
-		return o2 instanceof LuanTable ? getHandlerFunction(op,(LuanTable)o2) : null;
-	}
-
-	public LuanFunction getHandlerFunction(String op,LuanTable t) throws LuanException {
-		Object f = t.getHandler(op);
-		if( f == null )
-			return null;
-		return Luan.checkFunction(f);
-	}
-
-	public LuanTable toTable(Object obj) {
-		if( obj == null )
-			return null;
-		if( obj instanceof LuanTable )
-			return (LuanTable)obj;
-		if( obj instanceof List ) {
-			return new LuanTable(this,(List)obj);
-		}
-		if( obj instanceof Map ) {
-			return new LuanTable(this,(Map)obj);
-		}
-		if( obj instanceof Set ) {
-			return new LuanTable(this,(Set)obj);
-		}
-		Class cls = obj.getClass();
-		if( cls.isArray() ) {
-			if( cls.getComponentType().isPrimitive() ) {
-				int len = Array.getLength(obj);
-				List list = new ArrayList();
-				for( int i=0; i<len; i++ ) {
-					list.add(Array.get(obj,i));
-				}
-				return new LuanTable(this,list);
-			} else {
-				Object[] a = (Object[])obj;
-				return new LuanTable(this,Arrays.asList(a));
-			}
-		}
-		return null;
-	}
-
-}
--- a/src/luan/LuanTable.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/LuanTable.java	Tue Feb 12 22:33:40 2019 -0700
@@ -14,7 +14,7 @@
 
 
 public final class LuanTable implements LuanCloneable {
-	private LuanState luan;
+	private Luan luan;
 	private Map map = null;
 	private List list = null;
 	private LuanTable metatable = null;
@@ -22,11 +22,11 @@
 	private LuanCloner cloner;
 	private String security = null;
 
-	public LuanTable(LuanState luan) {
+	public LuanTable(Luan luan) {
 		this.luan = luan;
 	}
 
-	public LuanTable(LuanState luan,List list){
+	public LuanTable(Luan luan,List list){
 		int n = list.size();
 		for( int i=0; i<n; i++ ) {
 			Object val = list.get(i);
@@ -35,7 +35,7 @@
 		}
 	}
 
-	public LuanTable(LuanState luan,Map map) {
+	public LuanTable(Luan luan,Map map) {
 		this.luan = luan;
 		for( Object stupid : map.entrySet() ) {
 			Map.Entry entry = (Map.Entry)stupid;
@@ -46,7 +46,7 @@
 		}
 	}
 
-	public LuanTable(LuanState luan,Set set){
+	public LuanTable(Luan luan,Set set){
 		this.luan = luan;
 		for( Object el : set ) {
 			if( el != null )
@@ -93,7 +93,7 @@
 	}
 
 	private void deepenClone(LuanTable clone,LuanCloner cloner) {
-		clone.luan = (LuanState)cloner.clone(luan);
+		clone.luan = (Luan)cloner.clone(luan);
 		if( map != null ) {
 			Map newMap = newMap();
 			for( Object stupid : map.entrySet() ) {
@@ -370,7 +370,7 @@
 		return new LuanFunction() {
 			final Iterator<Map.Entry> iter = rawIterator();
 
-			@Override public Object[] call(LuanState luan,Object[] args) {
+			@Override public Object[] call(Luan luan,Object[] args) {
 				if( !iter.hasNext() )
 					return LuanFunction.NOTHING;
 				Map.Entry<Object,Object> entry = iter.next();
--- a/src/luan/host/Backup.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/host/Backup.java	Tue Feb 12 22:33:40 2019 -0700
@@ -12,7 +12,7 @@
 import org.apache.lucene.index.SnapshotDeletionPolicy;
 import org.apache.lucene.index.IndexCommit;
 import org.apache.lucene.store.FSDirectory;
-import luan.LuanState;
+import luan.Luan;
 import luan.LuanTable;
 import luan.LuanException;
 import luan.modules.PackageLuan;
@@ -61,13 +61,13 @@
 		}
 		String fromPath = from.getCanonicalPath() + "/";
 		LuanTable luceneInstances;
-		LuanState luan = null;
+		Luan luan = null;
 		try {
 			if( WebHandler.isServing() ) {
 				luceneInstances = (LuanTable)WebHandler.runLuan( from.getName(), getLucenes, "getLucenes" );
 			} else {
-				luan = new LuanState();
-				luan.onClose = new LuanState.OnClose() {
+				luan = new Luan();
+				luan.onClose = new Luan.OnClose() {
 					private final List<Closeable> onClose = new ArrayList<Closeable>();
 
 					public void onClose(Closeable c) {
--- a/src/luan/host/WebHandler.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/host/WebHandler.java	Tue Feb 12 22:33:40 2019 -0700
@@ -8,7 +8,6 @@
 import luan.webserver.Response;
 import luan.webserver.handlers.DomainHandler;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanException;
 import luan.LuanTable;
 import luan.LuanFunction;
@@ -39,7 +38,7 @@
 			String logDir = dirStr + "/site/private/local/logs/web";
 			new File(logDir).mkdirs();
 
-			LuanState luan = new LuanState();
+			Luan luan = new Luan();
 			try {
 				Log4j.newLoggerRepository(luan);
 			} catch(LuanException e) {
@@ -100,7 +99,7 @@
 		return true;
 	}
 */
-	static void initLuan(LuanState luan,String dir,String domain,boolean logging) {
+	static void initLuan(Luan luan,String dir,String domain,boolean logging) {
 		security(luan,dir);
 		try {
 			LuanFunction fn = BasicLuan.load_file(luan,"classpath:luan/host/init.luan");
@@ -122,10 +121,10 @@
 		}
 	}
 
-	private static final void security(LuanState luan,String dir) {
+	private static final void security(Luan luan,String dir) {
 		final String siteUri = "file:" + dir + "/site";
 		Luan.Security security = new Luan.Security() {
-			public void check(LuanState luan,LuanClosure closure,String op,Object... args)
+			public void check(Luan luan,LuanClosure closure,String op,Object... args)
 				throws LuanException
 			{
 				if( op.equals("uri") ) {
--- a/src/luan/impl/LuanCompiler.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/impl/LuanCompiler.java	Tue Feb 12 22:33:40 2019 -0700
@@ -5,7 +5,6 @@
 import java.util.Map;
 import java.util.HashMap;
 import luan.LuanFunction;
-import luan.LuanState;
 import luan.LuanException;
 import luan.LuanTable;
 import luan.LuanClosure;
--- a/src/luan/impl/LuanImpl.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/impl/LuanImpl.java	Tue Feb 12 22:33:40 2019 -0700
@@ -4,7 +4,6 @@
 import java.util.List;
 import java.util.ArrayList;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanFunction;
 import luan.LuanException;
@@ -30,7 +29,7 @@
 		throw new LuanException( "attempt to get length of a " + Luan.type(o) + " value" );
 	}
 
-	public static Object unm(LuanState luan,Object o) throws LuanException {
+	public static Object unm(Luan luan,Object o) throws LuanException {
 		if( o instanceof Number )
 			return -((Number)o).doubleValue();
 		if( o instanceof LuanTable ) {
@@ -42,7 +41,7 @@
 		throw new LuanException("attempt to perform arithmetic on a "+Luan.type(o)+" value");
 	}
 
-	private static Object arithmetic(LuanState luan,String op,Object o1,Object o2) throws LuanException {
+	private static Object arithmetic(Luan luan,String op,Object o1,Object o2) throws LuanException {
 		LuanFunction fn = luan.getBinHandler(op,o1,o2);
 		if( fn != null )
 			return Luan.first(fn.call(luan,new Object[]{o1,o2}));
@@ -50,25 +49,25 @@
 		throw new LuanException("attempt to perform arithmetic on a "+type+" value");
 	}
 
-	public static Object pow(LuanState luan,Object o1,Object o2) throws LuanException {
+	public static Object pow(Luan luan,Object o1,Object o2) throws LuanException {
 		if( o1 instanceof Number && o2 instanceof Number )
 			return Math.pow( ((Number)o1).doubleValue(), ((Number)o2).doubleValue() );
 		return arithmetic(luan,"__pow",o1,o2);
 	}
 
-	public static Object mul(LuanState luan,Object o1,Object o2) throws LuanException {
+	public static Object mul(Luan luan,Object o1,Object o2) throws LuanException {
 		if( o1 instanceof Number && o2 instanceof Number )
 			return ((Number)o1).doubleValue() * ((Number)o2).doubleValue();
 		return arithmetic(luan,"__mul",o1,o2);
 	}
 
-	public static Object div(LuanState luan,Object o1,Object o2) throws LuanException {
+	public static Object div(Luan luan,Object o1,Object o2) throws LuanException {
 		if( o1 instanceof Number && o2 instanceof Number )
 			return ((Number)o1).doubleValue() / ((Number)o2).doubleValue();
 		return arithmetic(luan,"__div",o1,o2);
 	}
 
-	public static Object mod(LuanState luan,Object o1,Object o2) throws LuanException {
+	public static Object mod(Luan luan,Object o1,Object o2) throws LuanException {
 		if( o1 instanceof Number && o2 instanceof Number ) {
 			double d1 = ((Number)o1).doubleValue();
 			double d2 = ((Number)o2).doubleValue();
@@ -77,19 +76,19 @@
 		return arithmetic(luan,"__mod",o1,o2);
 	}
 
-	public static Object add(LuanState luan,Object o1,Object o2) throws LuanException {
+	public static Object add(Luan luan,Object o1,Object o2) throws LuanException {
 		if( o1 instanceof Number && o2 instanceof Number )
 			return ((Number)o1).doubleValue() + ((Number)o2).doubleValue();
 		return arithmetic(luan,"__add",o1,o2);
 	}
 
-	public static Object sub(LuanState luan,Object o1,Object o2) throws LuanException {
+	public static Object sub(Luan luan,Object o1,Object o2) throws LuanException {
 		if( o1 instanceof Number && o2 instanceof Number )
 			return ((Number)o1).doubleValue() - ((Number)o2).doubleValue();
 		return arithmetic(luan,"__sub",o1,o2);
 	}
 
-	public static Object concat(LuanState luan,Object o1,Object o2) throws LuanException {
+	public static Object concat(Luan luan,Object o1,Object o2) throws LuanException {
 		LuanFunction fn = luan.getBinHandler("__concat",o1,o2);
 		if( fn != null )
 			return Luan.first(fn.call(luan,new Object[]{o1,o2}));
@@ -98,7 +97,7 @@
 		return s1 + s2;
 	}
 
-	public static boolean eq(LuanState luan,Object o1,Object o2) throws LuanException {
+	public static boolean eq(Luan luan,Object o1,Object o2) throws LuanException {
 		if( o1 == o2 || o1 != null && o1.equals(o2) )
 			return true;
 		if( o1 instanceof Number && o2 instanceof Number ) {
@@ -126,7 +125,7 @@
 		return Luan.checkBoolean( Luan.first(fn.call(luan,new Object[]{o1,o2})) );
 	}
 
-	public static boolean le(LuanState luan,Object o1,Object o2) throws LuanException {
+	public static boolean le(Luan luan,Object o1,Object o2) throws LuanException {
 		if( o1 instanceof Number && o2 instanceof Number ) {
 			Number n1 = (Number)o1;
 			Number n2 = (Number)o2;
@@ -146,7 +145,7 @@
 		throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) );
 	}
 
-	public static boolean lt(LuanState luan,Object o1,Object o2) throws LuanException {
+	public static boolean lt(Luan luan,Object o1,Object o2) throws LuanException {
 		return luan.isLessThan(o1,o2);
 	}
 
@@ -156,7 +155,7 @@
 
 	public static void nop(Object o) {}
 
-	public static void put(LuanState luan,Object t,Object key,Object value) throws LuanException {
+	public static void put(Luan luan,Object t,Object key,Object value) throws LuanException {
 		if( t instanceof LuanTable ) {
 			LuanTable tbl = (LuanTable)t;
 			tbl.put(key,value);
@@ -229,7 +228,7 @@
 		}
 	}
 
-	public static LuanTable table(LuanState luan,Object[] a) throws LuanException {
+	public static LuanTable table(Luan luan,Object[] a) throws LuanException {
 		LuanTable table = new LuanTable(luan);
 		int i = 0;
 		for( Object fld : a ) {
--- a/src/luan/impl/LuanParser.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/impl/LuanParser.java	Tue Feb 12 22:33:40 2019 -0700
@@ -9,7 +9,6 @@
 import java.util.ArrayList;
 import java.util.concurrent.atomic.AtomicInteger;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.modules.PackageLuan;
 
@@ -2012,7 +2011,6 @@
 			+"import luan.LuanClosure;  "
 			+"import luan.Luan;  "
 			+"import luan.LuanFunction;  "
-			+"import luan.LuanState;  "
 			+"import luan.LuanException;  "
 			+"import luan.modules.PackageLuan;  "
 
@@ -2022,7 +2020,7 @@
 					+ init(upValueSymbols)
 				+"}  "
 
-				+"@Override public Object doCall(LuanState luan,Object[] args) throws LuanException {  "
+				+"@Override public Object doCall(Luan luan,Object[] args) throws LuanException {  "
 					+"final Pointer[] parentUpValues = upValues;  "
 					+"Object t;  "
 					+"Object[] a;  "
@@ -2042,13 +2040,13 @@
 				+"{  "
 				+ init(upValueSymbols)
 				+"}  "
-				+"@Override public Object doCall(LuanState luan,Object[] args) throws LuanException {  "
+				+"@Override public Object doCall(Luan luan,Object[] args) throws LuanException {  "
 		);
 		if( name != null ) {
 			exp.add( ""
 					+"return _" + name + "(luan,args);  "
 				+"}  "
-				+"private Object _" + name + "(LuanState luan,Object[] args) throws LuanException {  "
+				+"private Object _" + name + "(Luan luan,Object[] args) throws LuanException {  "
 			);
 		}
 		exp.add( ""
--- a/src/luan/modules/BasicLuan.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/BasicLuan.java	Tue Feb 12 22:33:40 2019 -0700
@@ -9,7 +9,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanFunction;
 import luan.LuanException;
@@ -31,7 +30,7 @@
 		return Luan.load(text,sourceName,env);
 	}
 
-	public static LuanFunction load_file(LuanState luan,String fileName) throws LuanException {
+	public static LuanFunction load_file(Luan luan,String fileName) throws LuanException {
 		if( fileName == null ) {
 			fileName = "stdin:";
 		} else if( fileName.indexOf(':') == -1 ) {
@@ -55,7 +54,7 @@
 			int i = 0;
 			final int size = list.size();
 
-			@Override public Object[] call(LuanState luan,Object[] args) {
+			@Override public Object[] call(Luan luan,Object[] args) {
 				if( i >= size )
 					return LuanFunction.NOTHING;
 				Object val = list.get(i++);
@@ -104,11 +103,11 @@
 		throw new LuanException( "bad argument #1 to 'raw_len' (table or string expected)" );
 	}
 
-	public static String to_string(LuanState luan,Object v) throws LuanException {
+	public static String to_string(Luan luan,Object v) throws LuanException {
 		return luan.toString(v);
 	}
 
-	public static LuanTable new_error(LuanState luan,Object msg) throws LuanException {
+	public static LuanTable new_error(Luan luan,Object msg) throws LuanException {
 		String s = luan.toString(msg);
 		LuanTable tbl = new LuanException(s).table(luan);
 		tbl.rawPut( "message", msg );
@@ -138,7 +137,7 @@
 		return new LuanFunction() {
 			double v = from;
 
-			@Override public Object call(LuanState luan,Object[] args) {
+			@Override public Object call(Luan luan,Object[] args) {
 				if( step > 0.0 && v > to || step < 0.0 && v < to )
 					return LuanFunction.NOTHING;
 				double rtn = v;
@@ -152,7 +151,7 @@
 		return new LuanFunction() {
 			int i = 0;
 
-			@Override public Object call(LuanState luan,Object[] unused) {
+			@Override public Object call(Luan luan,Object[] unused) {
 				if( i >= args.length )
 					return LuanFunction.NOTHING;
 				Object val = args[i++];
@@ -165,7 +164,7 @@
 		return obj instanceof LuanFunction ? (LuanFunction)obj : null;
 	}
 
-	public static Object try_(LuanState luan,LuanTable blocks,Object... args) throws LuanException {
+	public static Object try_(Luan luan,LuanTable blocks,Object... args) throws LuanException {
 		Utils.checkNotNull(blocks);
 		Object obj = blocks.get(1);
 		if( obj == null )
@@ -199,7 +198,7 @@
 		}
 	}
 
-	@LuanMethod public static Object[] pcall(LuanState luan,LuanFunction f,Object... args) {
+	@LuanMethod public static Object[] pcall(Luan luan,LuanFunction f,Object... args) {
 		try {
 			Object[] r = Luan.array(f.call(luan,args));
 			Object[] rtn = new Object[r.length+1];
--- a/src/luan/modules/BinaryLuan.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/BinaryLuan.java	Tue Feb 12 22:33:40 2019 -0700
@@ -2,7 +2,6 @@
 
 import java.io.UnsupportedEncodingException;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanFunction;
 import luan.LuanException;
--- a/src/luan/modules/HtmlLuan.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/HtmlLuan.java	Tue Feb 12 22:33:40 2019 -0700
@@ -7,7 +7,6 @@
 import java.util.HashSet;
 import java.util.Map;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanException;
 
@@ -48,7 +47,7 @@
 	public static Set<String> containerTags = new HashSet<String>(Arrays.asList(SCRIPT,STYLE));
 */
 /*
-	public static LuanTable parse(LuanState luan,String text,LuanTable containerTagsTbl)
+	public static LuanTable parse(Luan luan,String text,LuanTable containerTagsTbl)
 		throws LuanException
 	{
 		Utils.checkNotNull(luan,text);
@@ -275,7 +274,7 @@
 
 
 /*
-	public static String to_string(LuanState luan,LuanTable tbl) throws LuanException {
+	public static String to_string(Luan luan,LuanTable tbl) throws LuanException {
 		List<Object> html = tbl.asList();
 		StringBuilder buf = new StringBuilder();
 		for( Object o : html ) {
@@ -306,7 +305,7 @@
 		return buf.toString();
 	}
 
-	private static String tagToString(LuanState luan,LuanTable tbl) throws LuanException {
+	private static String tagToString(Luan luan,LuanTable tbl) throws LuanException {
 		StringBuilder buf = new StringBuilder();
 		buf.append('<');
 		buf.append(tbl.get(luan,"name"));
--- a/src/luan/modules/IoLuan.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/IoLuan.java	Tue Feb 12 22:33:40 2019 -0700
@@ -29,7 +29,6 @@
 import java.util.Enumeration;
 import java.util.Map;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanFunction;
 import luan.LuanException;
@@ -47,7 +46,7 @@
 
 	public interface LuanWriter {
 		public Object out();
-		public void write(LuanState luan,Object... args) throws LuanException, IOException;
+		public void write(Luan luan,Object... args) throws LuanException, IOException;
 		public void close() throws IOException;
 	}
 
@@ -58,7 +57,7 @@
 				return out;
 			}
 
-			public void write(LuanState luan,Object... args) throws LuanException {
+			public void write(Luan luan,Object... args) throws LuanException {
 				for( Object obj : args ) {
 					out.print( luan.toString(obj) );
 				}
@@ -77,7 +76,7 @@
 				return out;
 			}
 
-			public void write(LuanState luan,Object... args) throws LuanException, IOException {
+			public void write(Luan luan,Object... args) throws LuanException, IOException {
 				for( Object obj : args ) {
 					out.write( luan.toString(obj) );
 				}
@@ -91,7 +90,7 @@
 
 	static LuanFunction lines(final BufferedReader in) {
 		return new LuanFunction() {
-			@Override public Object call(LuanState luan,Object[] args) throws LuanException {
+			@Override public Object call(Luan luan,Object[] args) throws LuanException {
 				try {
 					if( args.length > 0 ) {
 						if( args.length > 1 || !"close".equals(args[0]) )
@@ -114,7 +113,7 @@
 		return new LuanFunction() {
 			final byte[] a = new byte[blockSize];
 
-			@Override public Object call(LuanState luan,Object[] args) throws LuanException {
+			@Override public Object call(Luan luan,Object[] args) throws LuanException {
 				try {
 					if( args.length > 0 ) {
 						if( args.length > 1 || !"close".equals(args[0]) )
@@ -154,39 +153,39 @@
 	public static abstract class LuanIn {
 		protected String charset = null;
 
-		public abstract InputStream inputStream(LuanState luan) throws IOException, LuanException;
+		public abstract InputStream inputStream(Luan luan) throws IOException, LuanException;
 		public abstract String to_string();
 		public abstract String to_uri_string();
 
-		public Reader reader(LuanState luan) throws IOException, LuanException {
+		public Reader reader(Luan luan) throws IOException, LuanException {
 			InputStream in = inputStream(luan);
 			return charset==null ? new InputStreamReader(in) : new InputStreamReader(in,charset);
 		}
 
-		public String read_text(LuanState luan) throws IOException, LuanException {
+		public String read_text(Luan luan) throws IOException, LuanException {
 			Reader in = reader(luan);
 			String s = Utils.readAll(in);
 			in.close();
 			return s;
 		}
 
-		public byte[] read_binary(LuanState luan) throws IOException, LuanException {
+		public byte[] read_binary(Luan luan) throws IOException, LuanException {
 			InputStream in = inputStream(luan);
 			byte[] a = Utils.readAll(in);
 			in.close();
 			return a;
 		}
 
-		public LuanFunction read_lines(LuanState luan) throws IOException, LuanException {
+		public LuanFunction read_lines(Luan luan) throws IOException, LuanException {
 			return lines(new BufferedReader(reader(luan)));
 		}
 
-		public LuanFunction read_blocks(LuanState luan,Integer blockSize) throws IOException, LuanException {
+		public LuanFunction read_blocks(Luan luan,Integer blockSize) throws IOException, LuanException {
 			int n = blockSize!=null ? blockSize : Utils.bufSize;
 			return blocks(inputStream(luan),n);
 		}
 
-		public boolean exists(LuanState luan) throws IOException, LuanException {
+		public boolean exists(Luan luan) throws IOException, LuanException {
 			try {
 				inputStream(luan).close();
 				return true;
@@ -197,7 +196,7 @@
 			}
 		}
 
-		public long checksum(LuanState luan) throws IOException, LuanException {
+		public long checksum(Luan luan) throws IOException, LuanException {
 			long cs = 0;
 			InputStream in = new BufferedInputStream(inputStream(luan));
 			int c;
@@ -219,7 +218,7 @@
 
 	public static final LuanIn defaultStdin = new LuanIn() {
 
-		@Override public InputStream inputStream(LuanState luan) {
+		@Override public InputStream inputStream(Luan luan) {
 			return System.in;
 		}
 
@@ -231,15 +230,15 @@
 			return "stdin:";
 		}
 
-		@Override public String read_text(LuanState luan) throws IOException {
+		@Override public String read_text(Luan luan) throws IOException {
 			return Utils.readAll(new InputStreamReader(System.in));
 		}
 
-		@Override public byte[] read_binary(LuanState luan) throws IOException {
+		@Override public byte[] read_binary(Luan luan) throws IOException {
 			return Utils.readAll(System.in);
 		}
 
-		@Override public boolean exists(LuanState luan) {
+		@Override public boolean exists(Luan luan) {
 			return true;
 		}
 	};
@@ -252,7 +251,7 @@
 			return charset==null ? new OutputStreamWriter(out) : new OutputStreamWriter(out,charset);
 		}
 
-		public void write(LuanState luan,Object obj) throws LuanException, IOException {
+		public void write(Luan luan,Object obj) throws LuanException, IOException {
 			if( obj instanceof String ) {
 				String s = (String)obj;
 				Writer out = writer();
@@ -291,7 +290,7 @@
 			return new BufferedOutputStream(outputStream());
 		}
 
-		public void write_text(LuanState luan,Object... args) throws LuanException, IOException {
+		public void write_text(Luan luan,Object... args) throws LuanException, IOException {
 			LuanWriter luanWriter = luanWriter(new BufferedWriter(writer()));
 			luanWriter.write(luan,args);
 			luanWriter.close();
@@ -308,7 +307,7 @@
 			@Override public void write(int b) {}
 		};
 
-		@Override public InputStream inputStream(LuanState luan) {
+		@Override public InputStream inputStream(Luan luan) {
 			return in;
 		}
 
@@ -334,7 +333,7 @@
 			this.s = s;
 		}
 
-		@Override public InputStream inputStream(LuanState luan) {
+		@Override public InputStream inputStream(Luan luan) {
 			throw new UnsupportedOperationException();
 		}
 
@@ -350,15 +349,15 @@
 			return "string:" + s;
 		}
 
-		@Override public Reader reader(LuanState luan) {
+		@Override public Reader reader(Luan luan) {
 			return new StringReader(s);
 		}
 
-		@Override public String read_text(LuanState luan) {
+		@Override public String read_text(Luan luan) {
 			return s;
 		}
 
-		@Override public boolean exists(LuanState luan) {
+		@Override public boolean exists(Luan luan) {
 			return true;
 		}
 
@@ -370,7 +369,7 @@
 					return out;
 				}
 	
-				public void write(LuanState luan,Object... args) throws LuanException, IOException {
+				public void write(Luan luan,Object... args) throws LuanException, IOException {
 					for( Object obj : args ) {
 						out.write( luan.toString(obj) );
 					}
@@ -386,11 +385,11 @@
 	public static final class LuanFile extends LuanIO {
 		public final File file;
 
-		public LuanFile(LuanState luan,String path) throws LuanException {
+		public LuanFile(Luan luan,String path) throws LuanException {
 			this(luan,new File(path));
 		}
 
-		private LuanFile(LuanState luan,File file) throws LuanException {
+		private LuanFile(Luan luan,File file) throws LuanException {
 			this(file);
 			check(luan,"file:"+file.toString());
 		}
@@ -399,7 +398,7 @@
 			this.file = file;
 		}
 
-		@Override public InputStream inputStream(LuanState luan) throws IOException {
+		@Override public InputStream inputStream(Luan luan) throws IOException {
 			return new FileInputStream(file);
 		}
 
@@ -415,11 +414,11 @@
 			return "file:" + file.toString();
 		}
 
-		public LuanFile child(LuanState luan,String name) throws LuanException {
+		public LuanFile child(Luan luan,String name) throws LuanException {
 			return new LuanFile(luan,new File(file,name));
 		}
 
-		public LuanTable children(LuanState luan) throws LuanException {
+		public LuanTable children(Luan luan) throws LuanException {
 			File[] files = file.listFiles();
 			if( files==null )
 				return null;
@@ -430,14 +429,14 @@
 			return list;
 		}
 
-		public LuanFile parent(LuanState luan) throws LuanException, IOException {
+		public LuanFile parent(Luan luan) throws LuanException, IOException {
 			File parent = file.getParentFile();
 			if( parent==null )
 				parent = file.getCanonicalFile().getParentFile();
 			return new LuanFile(luan,parent);
 		}
 
-		@Override public boolean exists(LuanState luan) {
+		@Override public boolean exists(Luan luan) {
 			return file.exists();
 		}
 
@@ -449,11 +448,11 @@
 				throw new LuanException("couldn't rename file "+file+" to "+dest);
 		}
 
-		public LuanFile canonical(LuanState luan) throws LuanException, IOException {
+		public LuanFile canonical(Luan luan) throws LuanException, IOException {
 			return new LuanFile(luan,file.getCanonicalFile());
 		}
 
-		public LuanFile create_temp_file(LuanState luan,String prefix,String suffix) throws LuanException, IOException {
+		public LuanFile create_temp_file(Luan luan,String prefix,String suffix) throws LuanException, IOException {
 			File tmp = File.createTempFile(prefix,suffix,file);
 			return new LuanFile(luan,tmp);
 		}
@@ -495,7 +494,7 @@
 		}
 	}
 
-	public static LuanUrl classpath(LuanState luan,String name) throws LuanException {
+	public static LuanUrl classpath(Luan luan,String name) throws LuanException {
 		if( name.contains("//") )
 			return null;
 		String path = name;
@@ -547,7 +546,7 @@
 			this.dir = dir;
 		}
 
-		@Override public InputStream inputStream(LuanState luan) throws IOException {
+		@Override public InputStream inputStream(Luan luan) throws IOException {
 			return proc.getInputStream();
 		}
 
@@ -563,7 +562,7 @@
 			throw new UnsupportedOperationException();
 		}
 
-		@Override public boolean exists(LuanState luan) {
+		@Override public boolean exists(Luan luan) {
 			return true;
 		}
 
@@ -584,7 +583,7 @@
 			}
 		}
 
-		@Override public String read_text(LuanState luan) throws IOException, LuanException {
+		@Override public String read_text(Luan luan) throws IOException, LuanException {
 			String s = super.read_text(luan);
 			wait_for();
 			return s;
@@ -592,7 +591,7 @@
 	}
 
 	public static final class LuanOs extends BaseOs {
-		public LuanOs(LuanState luan,String cmd,LuanTable options) throws IOException, LuanException {
+		public LuanOs(Luan luan,String cmd,LuanTable options) throws IOException, LuanException {
 			super(cmd,options);
 			check(luan,"os:"+cmd);
 			this.proc = Runtime.getRuntime().exec(cmd,null,dir);
@@ -600,7 +599,7 @@
 	}
 
 	public static final class LuanBash extends BaseOs {
-		public LuanBash(LuanState luan,String cmd,LuanTable options) throws IOException, LuanException {
+		public LuanBash(Luan luan,String cmd,LuanTable options) throws IOException, LuanException {
 			super(cmd,options);
 			check(luan,"bash:"+cmd);
 			this.proc = Runtime.getRuntime().exec(new String[]{"bash","-c",cmd},null,dir);
@@ -615,7 +614,7 @@
 			this.in = in;
 		}
 
-		@Override public InputStream inputStream(LuanState luan) {
+		@Override public InputStream inputStream(Luan luan) {
 			return in;
 		}
 
@@ -627,7 +626,7 @@
 			throw new UnsupportedOperationException();
 		}
 
-		@Override public boolean exists(LuanState luan) {
+		@Override public boolean exists(Luan luan) {
 			return true;
 		}
 	};
@@ -641,7 +640,7 @@
 		}
 	}
 
-	public static LuanTable my_ips(LuanState luan) throws IOException, LuanException {
+	public static LuanTable my_ips(Luan luan) throws IOException, LuanException {
 		LuanTable tbl = new LuanTable(luan);
 		for( Enumeration<NetworkInterface> e1 = NetworkInterface.getNetworkInterfaces(); e1.hasMoreElements(); ) {
 			NetworkInterface ni = e1.nextElement();
@@ -655,7 +654,7 @@
 	}
 
 
-	private static void check(LuanState luan,String name) throws LuanException {
+	private static void check(Luan luan,String name) throws LuanException {
 		Luan.checkSecurity(luan,"uri",name);
 	}
 
--- a/src/luan/modules/JavaLuan.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/JavaLuan.java	Tue Feb 12 22:33:40 2019 -0700
@@ -18,7 +18,6 @@
 import java.util.Arrays;
 import java.util.Comparator;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanException;
 import luan.LuanFunction;
@@ -27,7 +26,7 @@
 
 public final class JavaLuan {
 
-	public static void java(LuanState luan) throws LuanException {
+	public static void java(Luan luan) throws LuanException {
 		Luan.checkSecurity(luan,"java");
 		luan.peek().javaOk = true;
 	}
@@ -35,18 +34,18 @@
 	public static final LuanFunction javaFn;
 	static {
 		try {
-			javaFn = new LuanJavaFunction(JavaLuan.class.getMethod("java",LuanState.class),null);
+			javaFn = new LuanJavaFunction(JavaLuan.class.getMethod("java",Luan.class),null);
 		} catch(NoSuchMethodException e) {
 			throw new RuntimeException(e);
 		}
 	}
 
-	private static void checkJava(LuanState luan) throws LuanException {
+	private static void checkJava(Luan luan) throws LuanException {
 		if( !luan.peek().javaOk )
 			throw new LuanException("Java isn't allowed");
 	}
 
-	public static Object __index(LuanState luan,Object obj,Object key) throws LuanException {
+	public static Object __index(Luan luan,Object obj,Object key) throws LuanException {
 		checkJava(luan);
 		Class cls;
 		if( obj instanceof Static ) {
@@ -136,7 +135,7 @@
 		}
 	}
 
-	public static void __new_index(LuanState luan,Object obj,Object key,Object value) throws LuanException {
+	public static void __new_index(Luan luan,Object obj,Object key,Object value) throws LuanException {
 		checkJava(luan);
 		Class cls;
 		if( obj instanceof Static ) {
@@ -310,7 +309,7 @@
 			return cls.isSynthetic();
 		}
 
-		public Object luan_proxy(final LuanState luan,final LuanTable t) throws LuanException {
+		public Object luan_proxy(final Luan luan,final LuanTable t) throws LuanException {
 			return Proxy.newProxyInstance(
 				cls.getClassLoader(),
 				new Class[]{cls},
@@ -334,14 +333,14 @@
 	private static final Method luan_proxyMethod;
 	static {
 		try {
-			luan_proxyMethod = Static.class.getMethod("luan_proxy",LuanState.class,LuanTable.class);
+			luan_proxyMethod = Static.class.getMethod("luan_proxy",Luan.class,LuanTable.class);
 			luan_proxyMethod.setAccessible(true);
 		} catch(NoSuchMethodException e) {
 			throw new RuntimeException(e);
 		}
 	}
 
-	public static Static load(LuanState luan,String name) throws LuanException {
+	public static Static load(Luan luan,String name) throws LuanException {
 		checkJava(luan);
 		Class cls;
 		try {
@@ -383,7 +382,7 @@
 			Collections.sort(varArgs,varArgsSorter);
 		}
 
-		@Override public Object call(LuanState luan,Object[] args) throws LuanException {
+		@Override public Object call(Luan luan,Object[] args) throws LuanException {
 			List<LuanJavaFunction> list = fnMap.get(args.length);
 			if( list != null ) {
 				for( LuanJavaFunction fn : list ) {
@@ -430,7 +429,7 @@
 			this.cls = cls;
 		}
 
-		public Object assertClass(LuanState luan,Object v) throws LuanException {
+		public Object assertClass(Luan luan,Object v) throws LuanException {
 			if( !cls.isInstance(v) ) {
 				String got = v.getClass().getSimpleName();
 				String expected = cls.getSimpleName();
@@ -442,7 +441,7 @@
 	private static final Method assertClass;
 	static {
 		try {
-			assertClass = AssertClass.class.getMethod("assertClass",LuanState.class,Object.class);
+			assertClass = AssertClass.class.getMethod("assertClass",Luan.class,Object.class);
 			assertClass.setAccessible(true);
 		} catch(NoSuchMethodException e) {
 			throw new RuntimeException(e);
@@ -450,7 +449,7 @@
 	}
 
 
-	public static Object proxy(final LuanState luan,Static st,final LuanTable t,final Object base) throws LuanException {
+	public static Object proxy(final Luan luan,Static st,final LuanTable t,final Object base) throws LuanException {
 		return Proxy.newProxyInstance(
 			st.cls.getClassLoader(),
 			new Class[]{st.cls},
--- a/src/luan/modules/MathLuan.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/MathLuan.java	Tue Feb 12 22:33:40 2019 -0700
@@ -1,11 +1,5 @@
 package luan.modules;
 
-import luan.Luan;
-import luan.LuanState;
-import luan.LuanTable;
-import luan.LuanFunction;
-import luan.LuanException;
-
 
 public final class MathLuan {
 
--- a/src/luan/modules/PackageLuan.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/PackageLuan.java	Tue Feb 12 22:33:40 2019 -0700
@@ -6,7 +6,6 @@
 import java.util.Arrays;
 import java.util.Collections;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanFunction;
 import luan.LuanJavaFunction;
@@ -19,13 +18,13 @@
 	public static final LuanFunction requireFn;
 	static {
 		try {
-			requireFn = new LuanJavaFunction(PackageLuan.class.getMethod("require",LuanState.class,String.class),null);
+			requireFn = new LuanJavaFunction(PackageLuan.class.getMethod("require",Luan.class,String.class),null);
 		} catch(NoSuchMethodException e) {
 			throw new RuntimeException(e);
 		}
 	}
 
-	public static LuanTable loaded(LuanState luan) {
+	public static LuanTable loaded(Luan luan) {
 		LuanTable tbl = (LuanTable)luan.registry().get("Package.loaded");
 		if( tbl == null ) {
 			tbl = new LuanTable(luan);
@@ -34,14 +33,14 @@
 		return tbl;
 	}
 
-	public static Object require(LuanState luan,String modName) throws LuanException {
+	public static Object require(Luan luan,String modName) throws LuanException {
 		Object mod = load(luan,modName);
 		if( mod.equals(Boolean.FALSE) )
 			throw new LuanException( "module '"+modName+"' not found" );
 		return mod;
 	}
 
-	public static Object load(LuanState luan,String modName) throws LuanException {
+	public static Object load(Luan luan,String modName) throws LuanException {
 		LuanTable loaded = loaded(luan);
 		Object mod = loaded.rawGet(modName);
 		if( mod == null ) {
@@ -86,7 +85,7 @@
 		return mod;
 	}
 
-	static String read(LuanState luan,String uri) {
+	static String read(Luan luan,String uri) {
 		LuanTable boot;
 		try {
 			boot = (LuanTable)luan.require("luan:Boot.luan");
@@ -104,7 +103,7 @@
 		}
 	}
 
-	public static void enableLoad(LuanState luan,String... mods) throws LuanException {
+	public static void enableLoad(Luan luan,String... mods) throws LuanException {
 		if( !luan.isLocked )
 			return;
 		LuanTable loaded = loaded(luan);
--- a/src/luan/modules/StringLuan.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/StringLuan.java	Tue Feb 12 22:33:40 2019 -0700
@@ -4,7 +4,6 @@
 import java.util.regex.Pattern;
 import java.util.regex.Matcher;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanFunction;
 import luan.LuanException;
@@ -131,7 +130,7 @@
 		Utils.checkNotNull(s);
 		final Matcher m = Pattern.compile(pattern).matcher(s);
 		return new LuanFunction() {
-			@Override public Object call(LuanState luan,Object[] args) {
+			@Override public Object call(Luan luan,Object[] args) {
 				if( !m.find() )
 					return null;
 				final int n = m.groupCount();
@@ -146,7 +145,7 @@
 		};
 	}
 
-	@LuanMethod public static Object[] gsub(LuanState luan,String s,String pattern,Object repl,Integer n) throws LuanException {
+	@LuanMethod public static Object[] gsub(Luan luan,String s,String pattern,Object repl,Integer n) throws LuanException {
 		Utils.checkNotNull(s);
 		int max = n==null ? Integer.MAX_VALUE : n;
 		final Matcher m = Pattern.compile(pattern).matcher(s);
@@ -210,7 +209,7 @@
 		return String.format(format,args);
 	}
 
-	public static String concat(LuanState luan,Object... args) throws LuanException {
+	public static String concat(Luan luan,Object... args) throws LuanException {
 		StringBuilder sb = new StringBuilder();
 		for( Object arg : args ) {
 			sb.append( luan.toString(arg) );
--- a/src/luan/modules/TableLuan.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/TableLuan.java	Tue Feb 12 22:33:40 2019 -0700
@@ -5,7 +5,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanFunction;
 import luan.LuanException;
@@ -15,7 +14,7 @@
 
 public final class TableLuan {
 
-	public static String concat(LuanState luan,LuanTable list,String sep,Integer i,Integer j) throws LuanException {
+	public static String concat(Luan luan,LuanTable list,String sep,Integer i,Integer j) throws LuanException {
 		int first = i==null ? 1 : i;
 		int last = j==null ? list.length() : j;
 		StringBuilder buf = new StringBuilder();
@@ -48,7 +47,7 @@
 		public boolean isLessThan(Object o1,Object o2);
 	}
 
-	public static void sort(final LuanState luan,LuanTable list,final LuanFunction comp) throws LuanException {
+	public static void sort(final Luan luan,LuanTable list,final LuanFunction comp) throws LuanException {
 		if( list.getMetatable() != null )
 			throw new LuanException("can't sort a table with a metatable");
 		final LessThan lt;
@@ -84,7 +83,7 @@
 		}
 	}
 
-	public static LuanTable pack(LuanState luan,Object... args) throws LuanException {
+	public static LuanTable pack(Luan luan,Object... args) throws LuanException {
 		LuanTable tbl = new LuanTable(luan,Arrays.asList(args));
 		tbl.rawPut( "n", args.length );
 		return tbl;
@@ -106,7 +105,7 @@
 		return list.toArray();
 	}
 
-	public static LuanTable copy(LuanState luan,LuanTable list,Integer from,Integer to) {
+	public static LuanTable copy(Luan luan,LuanTable list,Integer from,Integer to) {
 		if( from == null )
 			return new LuanTable(list);
 		if( to == null )
@@ -130,7 +129,7 @@
 		return tbl.rawSize();
 	}
 
-	public static LuanTable toTable(LuanState luan,Object obj) {
+	public static LuanTable toTable(Luan luan,Object obj) {
 		return luan.toTable(obj);
 	}
 
--- a/src/luan/modules/ThreadLuan.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/ThreadLuan.java	Tue Feb 12 22:33:40 2019 -0700
@@ -12,7 +12,6 @@
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanFunction;
 import luan.LuanTable;
 import luan.LuanException;
@@ -24,9 +23,9 @@
 	private static final Executor exec = Executors.newCachedThreadPool();
 	public static final ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1);
 
-	public static void fork(LuanState luan,LuanFunction fn) {
+	public static void fork(Luan luan,LuanFunction fn) {
 		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
-		final LuanState newLuan = (LuanState)cloner.clone(luan);
+		final Luan newLuan = (Luan)cloner.clone(luan);
 		final LuanFunction newFn = (LuanFunction)cloner.get(fn);
 		exec.execute(new Runnable(){public void run() {
 			try {
@@ -37,10 +36,10 @@
 		}});
 	}
 /*
-	public static LuanFunction synchronized_(final LuanState luan,final LuanFunction fn) throws LuanException {
+	public static LuanFunction synchronized_(final Luan luan,final LuanFunction fn) throws LuanException {
 		Utils.checkNotNull(fn);
 		return new LuanFunction() {
-			@Override public Object call(LuanState ingored,Object[] args) throws LuanException {
+			@Override public Object call(Luan ingored,Object[] args) throws LuanException {
 				synchronized(luan) {
 					return fn.call(luan,args);
 				}
@@ -48,11 +47,11 @@
 		};
 	}
 */
-	public static void schedule(LuanState luan,long delay,LuanFunction fn,String repeating)
+	public static void schedule(Luan luan,long delay,LuanFunction fn,String repeating)
 		throws LuanException
 	{
 		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
-		final LuanState newLuan = (LuanState)cloner.clone(luan);
+		final Luan newLuan = (Luan)cloner.clone(luan);
 		final LuanFunction newFn = (LuanFunction)cloner.get(fn);
 		Runnable r = new Runnable(){public void run() {
 			try {
@@ -130,7 +129,7 @@
 		}
 	}
 
-	private static Object makeSafe(LuanState luan,Object v) throws LuanException {
+	private static Object makeSafe(Luan luan,Object v) throws LuanException {
 		if( v instanceof LuanTable ) {
 			LuanTable tbl = (LuanTable)v;
 			if( tbl.getMetatable() != null )
@@ -164,15 +163,15 @@
 
 	public static final class Callable {
 		private long expires;
-		private final LuanState luan = new LuanState();
+		private final Luan luan = new Luan();
 		private final LuanTable fns;
 
-		Callable(LuanState luan,LuanTable fns) {
+		Callable(Luan luan,LuanTable fns) {
 			LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
 			this.fns = (LuanTable)cloner.get(fns);
 		}
 
-		public synchronized Object call(LuanState callerLuan,String fnName,Object... args) throws LuanException {
+		public synchronized Object call(Luan callerLuan,String fnName,Object... args) throws LuanException {
 			Object obj = makeSafe(luan,args);
 			if( obj instanceof Unsafe )
 				throw new LuanException("can't pass "+((Unsafe)obj).reason+" to global_callable "+Arrays.asList(args));
@@ -202,7 +201,7 @@
 		}
 	}
 
-	public static synchronized Callable globalCallable(LuanState luan,String name,LuanTable fns,long timeout) {
+	public static synchronized Callable globalCallable(Luan luan,String name,LuanTable fns,long timeout) {
 		Callable callable = callableMap.get(name);
 		if( callable == null ) {
 			sweep();
--- a/src/luan/modules/http/HttpServicer.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/http/HttpServicer.java	Tue Feb 12 22:33:40 2019 -0700
@@ -4,7 +4,7 @@
 import org.slf4j.LoggerFactory;
 import luan.webserver.Request;
 import luan.webserver.Response;
-import luan.LuanState;
+import luan.Luan;
 import luan.LuanFunction;
 import luan.LuanException;
 import luan.LuanTable;
@@ -15,7 +15,7 @@
 public final class HttpServicer {
 	private static final Logger logger = LoggerFactory.getLogger(HttpServicer.class);
 
-	public static Response service(LuanState luan,Request request,String modName)
+	public static Response service(Luan luan,Request request,String modName)
 		throws LuanException
 	{
 		try {
@@ -25,19 +25,19 @@
 		}
 	}
 
-	private static Response handleError(LuanState luan,Request request,LuanException e)
+	private static Response handleError(Luan luan,Request request,LuanException e)
 		throws LuanException
 	{
 //e.printStackTrace();
 		synchronized(luan) {
 			LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL);
-			luan = (LuanState)cloner.clone(luan);
+			luan = (Luan)cloner.clone(luan);
 		}
 		LuanTable module = (LuanTable)luan.require("luan:http/Http.luan");
 		return (Response)module.call( "handle_error", request, e.table(luan) );
 	}
 
-	private static Response serviceLuan(LuanState luan,Request request,String modName)
+	private static Response serviceLuan(Luan luan,Request request,String modName)
 		throws LuanException
 	{
 		LuanFunction fn;
@@ -50,7 +50,7 @@
 			if( !(mod instanceof LuanFunction) )
 				throw new LuanException( "module '"+modName+"' must return a function" );
 			LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL);
-			luan = (LuanState)cloner.clone(luan);
+			luan = (Luan)cloner.clone(luan);
 			fn = (LuanFunction)cloner.get(mod);
 		}
 
--- a/src/luan/modules/http/LuanDomainHandler.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/http/LuanDomainHandler.java	Tue Feb 12 22:33:40 2019 -0700
@@ -4,7 +4,7 @@
 import luan.webserver.Response;
 import luan.webserver.Handler;
 import luan.webserver.handlers.DomainHandler;
-import luan.LuanState;
+import luan.Luan;
 import luan.LuanTable;
 import luan.LuanCloner;
 import luan.LuanException;
@@ -13,26 +13,26 @@
 
 public class LuanDomainHandler implements Handler, DomainHandler.Factory {
 
-	private final LuanState luanInit;
+	private final Luan luanInit;
 	private final DomainHandler domainHandler = new DomainHandler(this);
 
-	public LuanDomainHandler(LuanState luanInit) {
+	public LuanDomainHandler(Luan luanInit) {
 		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
-		this.luanInit = (LuanState)cloner.clone(luanInit);
+		this.luanInit = (Luan)cloner.clone(luanInit);
 	}
 
 	@Override public Handler newHandler(String domain) {
-		LuanState luan = newLuan(domain);
+		Luan luan = newLuan(domain);
 		return new LuanHandler(luan);
 	}
 
-	protected void newLoggerRepository(LuanState luan) throws LuanException {
+	protected void newLoggerRepository(Luan luan) throws LuanException {
 		Log4j.newLoggerRepository(luan);
 	}
 
-	protected LuanState newLuan(String domain) {
+	protected Luan newLuan(String domain) {
 		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
-		LuanState luan = (LuanState)cloner.clone(luanInit);
+		Luan luan = (Luan)cloner.clone(luanInit);
 		try {
 			newLoggerRepository(luan);
 			LuanTable Http = (LuanTable)luan.require("luan:http/Http.luan");
--- a/src/luan/modules/http/LuanHandler.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/http/LuanHandler.java	Tue Feb 12 22:33:40 2019 -0700
@@ -20,7 +20,6 @@
 import luan.webserver.Handler;
 import luan.webserver.ResponseOutputStream;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanFunction;
 import luan.LuanJavaFunction;
@@ -31,12 +30,12 @@
 import luan.modules.logging.LuanLogger;
 
 
-public final class LuanHandler implements Handler, LuanState.OnClose {
-	private final LuanState luanInit;
+public final class LuanHandler implements Handler, Luan.OnClose {
+	private final Luan luanInit;
 	private final Logger logger;
 	private final ReadWriteLock lock = new ReentrantReadWriteLock();
 	private final List<Reference<Closeable>> onClose = new ArrayList<Reference<Closeable>>();
-	private volatile LuanState currentLuan;
+	private volatile Luan currentLuan;
 	private volatile boolean isDisabled = false;
 
 	private static final Method resetLuanMethod;
@@ -52,7 +51,7 @@
 		}
 	}
 
-	public LuanHandler(LuanState luanInit) {
+	public LuanHandler(Luan luanInit) {
 		this.luanInit = luanInit;
 		this.logger = LuanLogger.getLogger(luanInit,LuanHandler.class.getName());
 		try {
@@ -66,9 +65,9 @@
 		currentLuan = newLuan();
 	}
 
-	private LuanState newLuan() {
+	private Luan newLuan() {
 		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
-		LuanState luan = (LuanState)cloner.clone(luanInit);
+		Luan luan = (Luan)cloner.clone(luanInit);
 		luan.onClose = this;
 		try {
 			PackageLuan.load(luan,"site:/init.luan");
@@ -81,7 +80,7 @@
 	}
 
 /*
-	public LuanState getLuan() {
+	public Luan getLuan() {
 		return luan;
 	}
 */
@@ -138,7 +137,7 @@
 		lock.readLock().lock();
 		try {
 			LuanFunction fn;
-			LuanState luan = currentLuan;
+			Luan luan = currentLuan;
 			synchronized(luan) {
 				PackageLuan.enableLoad(luan,"luan:Rpc.luan");
 				LuanTable rpc = (LuanTable)luan.require("luan:Rpc.luan");
@@ -147,7 +146,7 @@
 				if( fn == null )
 					throw new LuanException( "function not found: " + fnName );
 				LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL);
-				luan = (LuanState)cloner.clone(luan);
+				luan = (Luan)cloner.clone(luan);
 				fn = (LuanFunction)cloner.get(fn);
 			}
 			return fn.call(luan,args);
@@ -178,10 +177,10 @@
 		lock.readLock().lock();
 		try {
 			LuanFunction fn = Luan.load(sourceText,sourceName);
-			LuanState luan = currentLuan;
+			Luan luan = currentLuan;
 			synchronized(luan) {
 				LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL);
-				LuanState luan2 = (LuanState)cloner.clone(luan);
+				Luan luan2 = (Luan)cloner.clone(luan);
 				return fn.call(luan2);
 			}
 		} finally {
@@ -190,11 +189,11 @@
 	}
 
 	public void eval_in_root(String text) throws LuanException {
-		LuanState oldLuan = currentLuan;
-		LuanState luan;
+		Luan oldLuan = currentLuan;
+		Luan luan;
 		synchronized(oldLuan) {
 			LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
-			luan = (LuanState)cloner.clone(oldLuan);
+			luan = (Luan)cloner.clone(oldLuan);
 		}
 		luan.onClose = this;
 		BasicLuan.load(text,"<eval_in_root>",null).call(luan);
--- a/src/luan/modules/logging/Log4j.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/logging/Log4j.java	Tue Feb 12 22:33:40 2019 -0700
@@ -7,7 +7,7 @@
 import org.apache.log4j.spi.LoggerRepository;
 import org.apache.log4j.spi.RootLogger;
 import org.apache.log4j.spi.RepositorySelector;
-import luan.LuanState;
+import luan.Luan;
 import luan.LuanException;
 import luan.LuanTable;
 
@@ -15,7 +15,7 @@
 public final class Log4j {
 	private static String KEY = "Logger.Repository";
 
-	public static void newLoggerRepository(LuanState luan) throws LuanException {
+	public static void newLoggerRepository(Luan luan) throws LuanException {
 		LoggerRepository lr =  new Hierarchy(new RootLogger(Level.DEBUG));
 		luan.registry().put(KEY,lr);
 		LuanTable module = (LuanTable)luan.require("luan:logging/Log4j.luan");
@@ -24,7 +24,7 @@
 
 	private static final LoggerRepository defaultLoggerRepository = LogManager.getLoggerRepository();
 
-	private static LoggerRepository getLoggerRepository(LuanState luan) {
+	private static LoggerRepository getLoggerRepository(Luan luan) {
 		LoggerRepository lr = (LoggerRepository)luan.registry().get(KEY);
 		return lr != null ? lr : defaultLoggerRepository;
 	}
@@ -32,17 +32,17 @@
 	static {
 		LogManager.setRepositorySelector( new RepositorySelector() {
 			public LoggerRepository getLoggerRepository() {
-				LuanState luan = LuanLogger.luan();
+				Luan luan = LuanLogger.luan();
 				return luan==null ? defaultLoggerRepository : Log4j.getLoggerRepository(luan);
 			}
 		}, new Object() );
 	}
 
-	public static Logger getRootLogger(LuanState luan) {
+	public static Logger getRootLogger(Luan luan) {
 		return getLoggerRepository(luan).getRootLogger();
 	}
 
-	public static Logger getLogger(LuanState luan,String name) {
+	public static Logger getLogger(Luan luan,String name) {
 		return getLoggerRepository(luan).getLogger(name);
 	}
 }
--- a/src/luan/modules/logging/LuanLogger.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/logging/LuanLogger.java	Tue Feb 12 22:33:40 2019 -0700
@@ -2,37 +2,37 @@
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import luan.LuanState;
+import luan.Luan;
 import luan.LuanException;
 
 
 public final class LuanLogger {
 	private final Logger logger;
 
-	public LuanLogger(LuanState luan,String name) {
+	public LuanLogger(Luan luan,String name) {
 		this.logger = getLogger(luan,name);
 	}
 
-	public void error(LuanState luan,Object obj) throws LuanException {
+	public void error(Luan luan,Object obj) throws LuanException {
 		logger.error( luan.toString(obj) );
 	}
 
-	public void warn(LuanState luan,Object obj) throws LuanException {
+	public void warn(Luan luan,Object obj) throws LuanException {
 		logger.warn( luan.toString(obj) );
 	}
 
-	public void info(LuanState luan,Object obj) throws LuanException {
+	public void info(Luan luan,Object obj) throws LuanException {
 		logger.info( luan.toString(obj) );
 	}
 
-	public void debug(LuanState luan,Object obj) throws LuanException {
+	public void debug(Luan luan,Object obj) throws LuanException {
 		logger.debug( luan.toString(obj) );
 	}
 
 
-	private static ThreadLocal<LuanState> tl = new ThreadLocal<LuanState>();
+	private static ThreadLocal<Luan> tl = new ThreadLocal<Luan>();
 
-	public static Logger getLogger(LuanState luan,String name) {
+	public static Logger getLogger(Luan luan,String name) {
 		try {
 			luan.require("luan:logging/Logging.luan");  // ensure initialization
 		} catch(LuanException e) {
@@ -46,7 +46,7 @@
 		}
 	}
 
-	public static LuanState luan() {
+	public static Luan luan() {
 		return tl.get();
 	}
 }
--- a/src/luan/modules/lucene/LuceneIndex.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/lucene/LuceneIndex.java	Tue Feb 12 22:33:40 2019 -0700
@@ -69,7 +69,6 @@
 import luan.lib.parser.ParseException;
 import luan.modules.Utils;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanFunction;
 import luan.LuanCloner;
@@ -103,10 +102,10 @@
 	private int writeCount;
 
 	private final ConcurrentMap<String,Map<String,LuanFunction>> indexedOnlyFields = new ConcurrentHashMap<String,Map<String,LuanFunction>>();
-	private final LuanState luanMine = new LuanState();
+	private final Luan luanMine = new Luan();
 	private final LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
 
-	public LuceneIndex(LuanState luan,String indexDirStr,FieldParser defaultFieldParser,String[] defaultFields)
+	public LuceneIndex(Luan luan,String indexDirStr,FieldParser defaultFieldParser,String[] defaultFields)
 		throws LuanException, IOException
 	{
 		mfp = defaultFieldParser==null ? new MultiFieldParser() : new MultiFieldParser(defaultFieldParser,defaultFields);
@@ -167,7 +166,7 @@
 		return new Term(key,br);
 	}
 
-	public void delete(LuanState luan,String queryStr) throws LuanException, IOException, ParseException {
+	public void delete(Luan luan,String queryStr) throws LuanException, IOException, ParseException {
 		Query query = SaneQueryParser.parseQuery(mfp,queryStr);
 
 		boolean commit = !writeLock.isHeldByCurrentThread();
@@ -188,7 +187,7 @@
 		map.put(field,fn);
 	}
 
-	public void save(LuanState luan,LuanTable doc) throws LuanException, IOException {
+	public void save(Luan luan,LuanTable doc) throws LuanException, IOException {
 		Set indexedOnlySet = new HashSet();
 		Object typeObj = doc.get("type");
 		if( typeObj==null )
@@ -231,7 +230,7 @@
 		}
 	}
 
-	public void update_in_transaction(LuanState luan,LuanFunction fn) throws IOException, LuanException {
+	public void update_in_transaction(Luan luan,LuanFunction fn) throws IOException, LuanException {
 		boolean commit = !writeLock.isHeldByCurrentThread();
 		writeLock.lock();
 		try {
@@ -243,7 +242,7 @@
 		}
 	}
 
-	public void run_in_lock(LuanState luan,LuanFunction fn) throws IOException, LuanException {
+	public void run_in_lock(Luan luan,LuanFunction fn) throws IOException, LuanException {
 		if( writeLock.isHeldByCurrentThread() )
 			throw new RuntimeException();
 		writeLock.lock();
@@ -278,7 +277,7 @@
 		}
 	}
 
-	public synchronized long nextId(LuanState luan) throws LuanException, IOException {
+	public synchronized long nextId(Luan luan) throws LuanException, IOException {
 		if( ++id > idLim ) {
 			idLim += idBatch;
 			LuanTable doc = new LuanTable(luan);
@@ -314,7 +313,7 @@
 		return snapshotDeletionPolicy;
 	}
 
-	public Object snapshot(LuanState luan,LuanFunction fn) throws LuanException, IOException {
+	public Object snapshot(Luan luan,LuanFunction fn) throws LuanException, IOException {
 		IndexCommit ic = snapshotDeletionPolicy.snapshot();
 		try {
 			String dir = fileDir.toString();
@@ -357,7 +356,7 @@
 			this.searcher = searcher;
 		}
 
-		@Override public Object call(LuanState luan,Object[] args) throws LuanException {
+		@Override public Object call(Luan luan,Object[] args) throws LuanException {
 			try {
 				return toTable(luan,searcher.doc(docID));
 			} catch(IOException e) {
@@ -403,7 +402,7 @@
 		close(openSearcher());
 	}
 
-	public int advanced_search( final LuanState luan, String queryStr, LuanFunction fn, Integer n, String sortStr ) throws LuanException, IOException, ParseException {
+	public int advanced_search( final Luan luan, String queryStr, LuanFunction fn, Integer n, String sortStr ) throws LuanException, IOException, ParseException {
 		Utils.checkNotNull(queryStr);
 		Query query = SaneQueryParser.parseQuery(mfp,queryStr);
 		IndexSearcher searcher = threadLocalSearcher.get();
@@ -452,7 +451,7 @@
 		}
 	}
 
-	public Object search_in_transaction(LuanState luan,LuanFunction fn) throws LuanException, IOException {
+	public Object search_in_transaction(Luan luan,LuanFunction fn) throws LuanException, IOException {
 		if( threadLocalSearcher.get() != null )
 			throw new LuanException("can't nest search_in_transaction calls");
 		IndexSearcher searcher = openSearcher();
@@ -557,7 +556,7 @@
 		throw new LuanException("invalid field type for "+ifld);
 	}
 
-	private static LuanTable toTable(LuanState luan,Document doc) throws LuanException {
+	private static LuanTable toTable(Luan luan,Document doc) throws LuanException {
 		if( doc==null )
 			return null;
 		LuanTable table = new LuanTable(luan);
@@ -589,7 +588,7 @@
 		}
 	};
 
-	public LuanFunction highlighter(LuanState luan,String queryStr,LuanFunction formatter,final Integer fragmentSize,String dotdotdot) throws ParseException {
+	public LuanFunction highlighter(Luan luan,String queryStr,LuanFunction formatter,final Integer fragmentSize,String dotdotdot) throws ParseException {
 		Query query = SaneQueryParser.parseQuery(mfp,queryStr);
 		Formatter fmt = new Formatter() {
 			public String highlightTerm(String originalText,TokenGroup tokenGroup) {
@@ -609,7 +608,7 @@
 		final Highlighter hl = new Highlighter(fmt,queryScorer);
 		hl.setTextFragmenter( new NullFragmenter() );
 		return new LuanFunction() {
-			@Override public String call(LuanState luan,Object[] args) throws LuanException {
+			@Override public String call(Luan luan,Object[] args) throws LuanException {
 				String text = (String)args[0];
 				try {
 					if( chooser != null ) {
--- a/src/luan/modules/mail/SmtpCon.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/mail/SmtpCon.java	Tue Feb 12 22:33:40 2019 -0700
@@ -16,7 +16,6 @@
 import javax.mail.internet.MimeMultipart;
 import javax.mail.internet.MimeBodyPart;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanException;
 
--- a/src/luan/modules/parsers/BBCode.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/parsers/BBCode.java	Tue Feb 12 22:33:40 2019 -0700
@@ -3,7 +3,6 @@
 import java.util.List;
 import java.util.ArrayList;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanFunction;
 import luan.LuanException;
 import luan.modules.Utils;
@@ -13,20 +12,20 @@
 
 public final class BBCode {
 
-	public static String toHtml(LuanState luan,String bbcode,LuanFunction quoter) throws LuanException {
+	public static String toHtml(Luan luan,String bbcode,LuanFunction quoter) throws LuanException {
 		return new BBCode(luan,bbcode,quoter,true).parse();
 	}
 
-	public static String toText(LuanState luan,String bbcode,LuanFunction quoter) throws LuanException {
+	public static String toText(Luan luan,String bbcode,LuanFunction quoter) throws LuanException {
 		return new BBCode(luan,bbcode,quoter,false).parse();
 	}
 
-	private final LuanState luan;
+	private final Luan luan;
 	private final Parser parser;
 	private final LuanFunction quoter;
 	private final boolean toHtml;
 
-	private BBCode(LuanState luan,String text,LuanFunction quoter,boolean toHtml) throws LuanException {
+	private BBCode(Luan luan,String text,LuanFunction quoter,boolean toHtml) throws LuanException {
 		Utils.checkNotNull(text,1);
 //		Utils.checkNotNull(quoter,2);
 		this.luan = luan;
--- a/src/luan/modules/parsers/Css.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/parsers/Css.java	Tue Feb 12 22:33:40 2019 -0700
@@ -1,6 +1,6 @@
 package luan.modules.parsers;
 
-import luan.LuanState;
+import luan.Luan;
 import luan.LuanTable;
 import luan.LuanException;
 import luan.lib.parser.Parser;
@@ -8,7 +8,7 @@
 
 public final class Css {
 
-	public static LuanTable style(LuanState luan,String text) {
+	public static LuanTable style(Luan luan,String text) {
 		try {
 			return new Css(luan,text).parseStyle();
 		} catch(LuanException e) {
@@ -16,10 +16,10 @@
 		}
 	}
 
-	private final LuanState luan;
+	private final Luan luan;
 	private final Parser parser;
 
-	private Css(LuanState luan,String text) {
+	private Css(Luan luan,String text) {
 		this.luan = luan;
 		this.parser = new Parser(text);
 	}
--- a/src/luan/modules/parsers/Csv.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/parsers/Csv.java	Tue Feb 12 22:33:40 2019 -0700
@@ -1,6 +1,6 @@
 package luan.modules.parsers;
 
-import luan.LuanState;
+import luan.Luan;
 import luan.LuanTable;
 import luan.LuanException;
 import luan.lib.parser.Parser;
@@ -9,7 +9,7 @@
 
 public final class Csv {
 
-	public static LuanTable toList(LuanState luan,String line) throws ParseException {
+	public static LuanTable toList(Luan luan,String line) throws ParseException {
 		try {
 			return new Csv(line).parse(luan);
 		} catch(LuanException e) {
@@ -27,7 +27,7 @@
 		return new ParseException(parser,msg);
 	}
 
-	private LuanTable parse(LuanState luan) throws ParseException, LuanException {
+	private LuanTable parse(Luan luan) throws ParseException, LuanException {
 		LuanTable list = new LuanTable(luan);
 		while(true) {
 			Spaces();
--- a/src/luan/modules/parsers/Html.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/parsers/Html.java	Tue Feb 12 22:33:40 2019 -0700
@@ -4,7 +4,7 @@
 import java.util.ArrayList;
 import java.util.Set;
 import java.util.HashSet;
-import luan.LuanState;
+import luan.Luan;
 import luan.LuanTable;
 import luan.LuanException;
 import luan.lib.parser.Parser;
@@ -12,7 +12,7 @@
 
 public final class Html {
 
-	public static LuanTable toList(LuanState luan,String text,LuanTable containerTagsTbl) {
+	public static LuanTable toList(Luan luan,String text,LuanTable containerTagsTbl) {
 		try {
 			return new Html(luan,text,containerTagsTbl).parse();
 		} catch(LuanException e) {
@@ -20,11 +20,11 @@
 		}
 	}
 
-	private final LuanState luan;
+	private final Luan luan;
 	private final Parser parser;
 	private final Set<String> containerTags = new HashSet<String>();
 
-	private Html(LuanState luan,String text,LuanTable containerTagsTbl) {
+	private Html(Luan luan,String text,LuanTable containerTagsTbl) {
 		this.luan = luan;
 		this.parser = new Parser(text);
 		for( Object v : containerTagsTbl.asList() ) {
--- a/src/luan/modules/sql/Database.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/sql/Database.java	Tue Feb 12 22:33:40 2019 -0700
@@ -11,7 +11,6 @@
 import java.util.Properties;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanException;
 
--- a/src/luan/modules/url/LuanUrl.java	Tue Feb 12 21:50:26 2019 -0700
+++ b/src/luan/modules/url/LuanUrl.java	Tue Feb 12 22:33:40 2019 -0700
@@ -19,7 +19,6 @@
 import java.util.Base64;
 import luan.lib.parser.ParseException;
 import luan.Luan;
-import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanJavaFunction;
 import luan.LuanException;
@@ -196,7 +195,7 @@
 		return t==null ? null : t.asMap();
 	}
 
-	@Override public InputStream inputStream(LuanState luan) throws IOException, LuanException {
+	@Override public InputStream inputStream(Luan luan) throws IOException, LuanException {
 		try {
 			return inputStream(luan,null);
 		} catch(AuthException e) {
@@ -208,7 +207,7 @@
 		}
 	}
 
-	private InputStream inputStream(LuanState luan,String authorization)
+	private InputStream inputStream(Luan luan,String authorization)
 		throws IOException, LuanException, AuthException
 	{
 		URLConnection con = url.openConnection();
@@ -270,7 +269,7 @@
 		}
 	}
 
-	private InputStream getInputStream(LuanState luan,HttpURLConnection httpCon,String authorization)
+	private InputStream getInputStream(Luan luan,HttpURLConnection httpCon,String authorization)
 		throws IOException, LuanException, AuthException
 	{
 		try {