changeset 672:d3e5414bdf4c

better java permission handling
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 12 Apr 2016 17:03:30 -0600
parents 82f130eba7b0
children 33629d753cf9
files core/src/luan/Luan.java core/src/luan/LuanJava.java core/src/luan/LuanState.java core/src/luan/LuanTable.java core/src/luan/impl/AddExpr.java core/src/luan/impl/AndExpr.java core/src/luan/impl/BinaryOpExpr.java core/src/luan/impl/BreakStmt.java core/src/luan/impl/Closure.java core/src/luan/impl/ConcatExpr.java core/src/luan/impl/ConstExpr.java core/src/luan/impl/DivExpr.java core/src/luan/impl/EqExpr.java core/src/luan/impl/ExpList.java core/src/luan/impl/Expr.java core/src/luan/impl/ExprImpl.java core/src/luan/impl/Expressions.java core/src/luan/impl/ExpressionsExpr.java core/src/luan/impl/ExpressionsStmt.java core/src/luan/impl/FnCall.java core/src/luan/impl/IfStmt.java core/src/luan/impl/IndexExpr.java core/src/luan/impl/LeExpr.java core/src/luan/impl/LenExpr.java core/src/luan/impl/LtExpr.java core/src/luan/impl/LuanCompiler.java core/src/luan/impl/LuanImpl.java core/src/luan/impl/LuanParser.java core/src/luan/impl/LuanStateImpl.java core/src/luan/impl/ModExpr.java core/src/luan/impl/MulExpr.java core/src/luan/impl/NotExpr.java core/src/luan/impl/OrExpr.java core/src/luan/impl/PowExpr.java core/src/luan/impl/RepeatStmt.java core/src/luan/impl/ReturnStmt.java core/src/luan/impl/SetStmt.java core/src/luan/impl/SetTableEntry.java core/src/luan/impl/Settable.java core/src/luan/impl/Stmt.java core/src/luan/impl/StmtExp.java core/src/luan/impl/SubExpr.java core/src/luan/impl/TableExpr.java core/src/luan/impl/UnaryOpExpr.java core/src/luan/impl/UnmExpr.java core/src/luan/impl/WhileStmt.java core/src/luan/modules/JavaLuan.java
diffstat 47 files changed, 70 insertions(+), 952 deletions(-) [+]
line wrap: on
line diff
--- a/core/src/luan/Luan.java	Tue Apr 12 14:44:10 2016 -0600
+++ b/core/src/luan/Luan.java	Tue Apr 12 17:03:30 2016 -0600
@@ -7,7 +7,7 @@
 public final class Luan {
 
 	public static void main(String[] args) throws LuanException {
-		LuanState luan = LuanState.newInstance();
+		LuanState luan = new LuanState();
 		LuanFunction standalone = (LuanFunction)BasicLuan.load_file(luan,"classpath:luan/cmd_line.luan",null);
 		standalone.call(luan,args);
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/src/luan/LuanJava.java	Tue Apr 12 17:03:30 2016 -0600
@@ -0,0 +1,17 @@
+package luan;
+
+import luan.DeepCloneable;
+import luan.DeepCloner;
+
+
+public final class LuanJava implements DeepCloneable {
+	public boolean ok = false;
+
+	@Override public LuanJava shallowClone() {
+		LuanJava java = new LuanJava();
+		java.ok = ok;
+		return java;
+	}
+
+	@Override public void deepenClone(DeepCloneable clone,DeepCloner cloner) {}
+}
--- a/core/src/luan/LuanState.java	Tue Apr 12 14:44:10 2016 -0600
+++ b/core/src/luan/LuanState.java	Tue Apr 12 17:03:30 2016 -0600
@@ -13,23 +13,28 @@
 import luan.modules.JavaLuan;
 
 
-public abstract class LuanState implements DeepCloneable {
+public final class LuanState implements DeepCloneable {
 
+	public LuanJava java;
 	private Map registry;
 	private final List<Reference<Closeable>> onClose = new ArrayList<Reference<Closeable>>();
 
-	protected LuanState() {
+	public LuanState() {
+		java = new LuanJava();
 		registry = new HashMap();
 	}
 
-	protected LuanState(LuanState luan) {}
+	private LuanState(LuanState luan) {}
 
-	@Override public void deepenClone(DeepCloneable clone,DeepCloner cloner) {
-		((LuanState)clone).registry = cloner.deepClone(registry);
+	@Override public LuanState shallowClone() {
+		return new LuanState(this);
 	}
 
-	public abstract boolean hasJava();
-	public abstract void setJava();
+	@Override public void deepenClone(DeepCloneable dc,DeepCloner cloner) {
+		LuanState clone = (LuanState)dc;
+		clone.registry = cloner.deepClone(registry);
+		clone.java = (LuanJava)cloner.deepClone(java);
+	}
 
 	public final Map registry() {
 		return registry;
@@ -48,10 +53,6 @@
 		onClose.clear();
 	}
 
-	public static LuanState newInstance() {
-		return LuanCompiler.newLuanState();
-	}
-
 	public final Object eval(String cmd) throws LuanException {
 		return eval(cmd,new LuanTable());
 	}
@@ -81,7 +82,7 @@
 			LuanTable tbl = (LuanTable)obj;
 			return tbl.get(this,key);
 		}
-		if( obj != null && hasJava() )
+		if( obj != null && java.ok )
 			return JavaLuan.__index(this,obj,key,false);
 		throw new LuanException("attempt to index a " + Luan.type(obj) + " value" );
 	}
--- a/core/src/luan/LuanTable.java	Tue Apr 12 14:44:10 2016 -0600
+++ b/core/src/luan/LuanTable.java	Tue Apr 12 17:03:30 2016 -0600
@@ -17,7 +17,7 @@
 	private Map map = null;
 	private List list = null;
 	private LuanTable metatable = null;
-	public boolean hasJava = false;
+	public LuanJava java;
 
 	public LuanTable() {}
 
@@ -76,7 +76,7 @@
 		}
 		if( metatable != null )
 			clone.metatable = (LuanTable)cloner.get(metatable);
-		clone.hasJava = hasJava;
+		clone.java = (LuanJava)cloner.deepClone(java);
 	}
 
 	public boolean isList() {
--- a/core/src/luan/impl/AddExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-
-
-final class AddExpr extends BinaryOpExpr {
-
-	AddExpr(Expr op1,Expr op2) {
-		super(op1,op2);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		Object o1 = op1.eval(luan);
-		Object o2 = op2.eval(luan);
-		if( o1 instanceof Number && o2 instanceof Number )
-			return ((Number)o1).doubleValue() + ((Number)o2).doubleValue();
-		return arithmetic(luan,"__add",o1,o2);
-	}
-}
--- a/core/src/luan/impl/AndExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanException;
-
-
-final class AndExpr extends BinaryOpExpr implements StmtExp {
-
-	AndExpr(Expr op1,Expr op2) {
-		super(op1,op2);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		Object v1 = op1.eval(luan);
-		return v1 == null || Boolean.FALSE.equals(v1) ? v1 : op2.eval(luan);
-	}
-}
--- a/core/src/luan/impl/BinaryOpExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanTable;
-import luan.LuanFunction;
-import luan.LuanException;
-
-
-abstract class BinaryOpExpr extends CodeImpl implements Expr {
-	final Expr op1;
-	final Expr op2;
-
-	BinaryOpExpr(Expr op1,Expr op2) {
-		this.op1 = op1;
-		this.op2 = op2;
-	}
-
-	Object arithmetic(LuanStateImpl 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}));
-		String type = !(o1 instanceof Number) ? Luan.type(o1) : Luan.type(o2);
-		throw new LuanException("attempt to perform arithmetic on a "+type+" value");
-	}
-
-}
--- a/core/src/luan/impl/BreakStmt.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-package luan.impl;
-
-
-final class BreakStmt implements Stmt {
-
-	@Override public void eval(LuanStateImpl luan) {
-		throw new BreakException();
-	}
-}
--- a/core/src/luan/impl/Closure.java	Tue Apr 12 14:44:10 2016 -0600
+++ b/core/src/luan/impl/Closure.java	Tue Apr 12 17:03:30 2016 -0600
@@ -6,13 +6,16 @@
 import luan.LuanException;
 import luan.DeepCloner;
 import luan.DeepCloneable;
+import luan.LuanJava;
 
 
 public abstract class Closure extends LuanFunction implements DeepCloneable, Cloneable {
 	public Pointer[] upValues;
+	public LuanJava java;
 
-	public Closure(int nUpValues) throws LuanException {
+	public Closure(int nUpValues,LuanJava java) throws LuanException {
 		this.upValues = new Pointer[nUpValues];
+		this.java = java;
 	}
 
 	@Override public Closure shallowClone() {
@@ -23,18 +26,19 @@
 		}
 	}
 
-	@Override public void deepenClone(DeepCloneable clone,DeepCloner cloner) {
-		((Closure)clone).upValues = (Pointer[])cloner.deepClone(upValues);
+	@Override public void deepenClone(DeepCloneable dc,DeepCloner cloner) {
+		Closure clone = (Closure)dc;
+		clone.upValues = (Pointer[])cloner.deepClone(upValues);
+		clone.java = (LuanJava)cloner.deepClone(java);
 	}
 
-	@Override public final Object call(LuanState ls,Object[] args) throws LuanException {
-		LuanStateImpl luan = (LuanStateImpl)ls;
-		Closure old = luan.closure;
-		luan.closure = this;
+	@Override public final Object call(LuanState luan,Object[] args) throws LuanException {
+		LuanJava old = luan.java;
+		luan.java = java;
 		try {
 			return doCall(luan,args);
 		} finally {
-			luan.closure = old;
+			luan.java = old;
 		}	
 	}
 
--- a/core/src/luan/impl/ConcatExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanFunction;
-import luan.LuanException;
-
-
-final class ConcatExpr extends BinaryOpExpr {
-
-	ConcatExpr(Expr op1,Expr op2) {
-		super(op1,op2);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		Object o1 = op1.eval(luan);
-		Object o2 = op2.eval(luan);
-		LuanFunction fn = Luan.getBinHandler("__concat",o1,o2);
-		if( fn != null )
-			return Luan.first(fn.call(luan,new Object[]{o1,o2}));
-		String s1 = luan.toString(o1);
-		String s2 = luan.toString(o2);
-		return s1 + s2;
-	}
-}
--- a/core/src/luan/impl/ConstExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-package luan.impl;
-
-
-final class ConstExpr extends CodeImpl implements Expr {
-	private final Object obj;
-
-	ConstExpr(Object obj) {
-		this.obj = obj;
-	}
-
-	@Override public Object eval(LuanStateImpl luan) {
-		return obj;
-	}
-
-	@Override public String toString() {
-		return "(ConstExpr "+obj+")";
-	}
-}
--- a/core/src/luan/impl/DivExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-
-
-final class DivExpr extends BinaryOpExpr {
-
-	DivExpr(Expr op1,Expr op2) {
-		super(op1,op2);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		Object o1 = op1.eval(luan);
-		Object o2 = op2.eval(luan);
-		if( o1 instanceof Number && o2 instanceof Number )
-			return ((Number)o1).doubleValue() / ((Number)o2).doubleValue();
-		return arithmetic(luan,"__div",o1,o2);
-	}
-}
--- a/core/src/luan/impl/EqExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-package luan.impl;
-
-import java.util.Arrays;
-import luan.Luan;
-import luan.LuanFunction;
-import luan.LuanTable;
-import luan.LuanException;
-
-
-final class EqExpr extends BinaryOpExpr {
-
-	EqExpr(Expr op1,Expr op2) {
-		super(op1,op2);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		return eq(luan);
-	}
-
-	private boolean eq(LuanStateImpl luan) throws LuanException {
-		Object o1 = op1.eval(luan);
-		Object o2 = op2.eval(luan);
-		if( o1 == o2 || o1 != null && o1.equals(o2) )
-			return true;
-		if( o1 instanceof Number && o2 instanceof Number ) {
-			Number n1 = (Number)o1;
-			Number n2 = (Number)o2;
-			return n1.doubleValue() == n2.doubleValue();
-		}
-		if( o1 instanceof byte[] && o2 instanceof byte[] ) {
-			byte[] b1 = (byte[])o1;
-			byte[] b2 = (byte[])o2;
-			return Arrays.equals(b1,b2);
-		}
-		if( !(o1 instanceof LuanTable && o2 instanceof LuanTable) )
-			return false;
-		LuanTable t1 = (LuanTable)o1;
-		LuanTable t2 = (LuanTable)o2;
-		LuanTable mt1 = t1.getMetatable();
-		LuanTable mt2 = t2.getMetatable();
-		if( mt1==null || mt2==null )
-			return false;
-		Object f = mt1.rawGet("__eq");
-		if( f == null || !f.equals(mt2.rawGet("__eq")) )
-			return false;
-		LuanFunction fn = Luan.checkFunction(f);
-		return Luan.checkBoolean( Luan.first(fn.call(luan,new Object[]{o1,o2})) );
-	}
-
-	@Override public String toString() {
-		return "(EqExpr "+op1+" "+op2+")";
-	}
-}
--- a/core/src/luan/impl/ExpList.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-package luan.impl;
-
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
-import luan.LuanException;
-import luan.LuanFunction;
-import luan.Luan;
-
-
-final class ExpList {
-
-	static final Expressions emptyExpList = new Expressions() {
-
-		@Override public Object[] eval(LuanStateImpl luan) {
-			return LuanFunction.NOTHING;
-		}
-	};
-
-	private static Expr[] toArray(List<Expressions> list) {
-		Expr[] a = new Expr[list.size()];
-		for( int i=0; i<a.length; i++ ) {
-			Expressions exprs = list.get(i);
-			if( exprs instanceof Expr ) {
-				a[i] = (Expr)exprs;
-			} else {
-				a[i] = new ExpressionsExpr(exprs);
-			}
-		}
-		return a;
-	}
-
-	static Expressions build(List<Expressions> list) {
-		switch(list.size()) {
-		case 0:
-			return emptyExpList;
-		case 1:
-			return list.get(0);
-		default:
-			if( list.get(list.size()-1) instanceof Expr ) {
-				return new ExprList1( toArray(list) );
-			} else {
-				Expressions last = list.remove(list.size()-1);
-				return new ExprList2( toArray(list), last );
-			}
-		}
-	}
-
-	private static class ExprList1 implements Expressions {
-		private final Expr[] exprs;
-
-		private ExprList1(Expr[] exprs) {
-			this.exprs = exprs;
-		}
-	
-		@Override public Object eval(LuanStateImpl luan) throws LuanException {
-			Object[] a = new Object[exprs.length];
-			for( int i=0; i<exprs.length; i++ ) {
-				a[i] = exprs[i].eval(luan);
-			}
-			return a;
-		}
-	}
-
-	private static class ExprList2 implements Expressions {
-		private final Expr[] exprs;
-		private final Expressions last;
-	
-		private ExprList2(Expr[] exprs,Expressions last) {
-			this.exprs = exprs;
-			this.last = last;
-		}
-	
-		@Override public Object eval(LuanStateImpl luan) throws LuanException {
-			List<Object> list = new ArrayList<Object>();
-			for( Expr expr : exprs ) {
-				list.add( expr.eval(luan) );
-			}
-			list.addAll( Arrays.asList(Luan.array( last.eval(luan) )) );
-			return list.toArray();
-		}
-	}
-}
--- a/core/src/luan/impl/Expr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-
-
-public interface Expr extends Expressions {}
--- a/core/src/luan/impl/ExprImpl.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-package luan.impl;
-
-
-abstract class ExprImpl extends CodeImpl implements Expr {}
--- a/core/src/luan/impl/Expressions.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-
-
-public interface Expressions extends Code {
-	public Object eval(LuanStateImpl luan) throws LuanException;
-}
--- a/core/src/luan/impl/ExpressionsExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-package luan.impl;
-
-import java.util.List;
-import luan.Luan;
-import luan.LuanException;
-
-
-final class ExpressionsExpr implements Expr {
-	private final Expressions expressions;
-
-	ExpressionsExpr(Expressions expressions) {
-		if( expressions==null )
-			throw new NullPointerException();
-		this.expressions = expressions;
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		return Luan.first( expressions.eval(luan) );
-	}
-
-}
--- a/core/src/luan/impl/ExpressionsStmt.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-
-
-final class ExpressionsStmt implements Stmt {
-	private final Expressions expressions;
-
-	ExpressionsStmt(Expressions expressions) {
-		this.expressions = expressions;
-	}
-
-	@Override public void eval(LuanStateImpl luan) throws LuanException {
-		expressions.eval(luan);
-	}
-
-}
--- a/core/src/luan/impl/FnCall.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanFunction;
-import luan.LuanException;
-import luan.LuanTable;
-
-
-final class FnCall extends CodeImpl implements StmtExp {
-	final Expr fnExpr;
-	final Expressions args;
-
-	FnCall(Expr fnExpr,Expressions args) {
-		this.fnExpr = fnExpr;
-		this.args = args;
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		return call( luan, fnExpr.eval(luan), Luan.array(args.eval(luan)) );
-	}
-
-	private Object call(LuanStateImpl luan,Object o,Object[] argVals) throws LuanException {
-		if( o instanceof LuanFunction ) {
-			LuanFunction fn = (LuanFunction)o;
-			return fn.call( luan, argVals );
-		}
-		if( o instanceof LuanTable ) {
-			LuanTable t = (LuanTable)o;
-			Object h = t.getHandler("__call");
-			if( h != null )
-				return call(luan,h,argVals);
-		}
-		throw new LuanException( "attempt to call a " + Luan.type(o) + " value" );
-	}
-
-	@Override public String toString() {
-		return "(FnCall "+fnExpr+" "+args+")";
-	}
-}
--- a/core/src/luan/impl/IfStmt.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanException;
-
-
-final class IfStmt extends CodeImpl implements Stmt {
-	private final Expr cnd;
-	final Stmt thenStmt;
-	final Stmt elseStmt;
-
-	IfStmt(Expr cnd,Stmt thenStmt,Stmt elseStmt) {
-		this.cnd = cnd;
-		this.thenStmt = thenStmt;
-		this.elseStmt = elseStmt;
-	}
-
-	@Override public void eval(LuanStateImpl luan) throws LuanException {
-		if( Luan.checkBoolean( cnd.eval(luan) ) ) {
-			thenStmt.eval(luan);
-		} else {
-			elseStmt.eval(luan);
-		}
-	}
-}
--- a/core/src/luan/impl/IndexExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-
-
-final class IndexExpr extends BinaryOpExpr {
-
-	IndexExpr(Expr op1,Expr op2) {
-		super(op1,op2);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		Object o1 = op1.eval(luan);
-		Object o2 = op2.eval(luan);
-		return luan.index(o1,o2);
-	}
-
-}
--- a/core/src/luan/impl/LeExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanFunction;
-import luan.LuanException;
-
-
-final class LeExpr extends BinaryOpExpr {
-
-	LeExpr(Expr op1,Expr op2) {
-		super(op1,op2);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		return le(luan);
-	}
-
-	private boolean le(LuanStateImpl luan) throws LuanException {
-		Object o1 = op1.eval(luan);
-		Object o2 = op2.eval(luan);
-		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 = Luan.getBinHandler("__le",o1,o2);
-		if( fn != null )
-			return Luan.checkBoolean( Luan.first(fn.call(luan,new Object[]{o1,o2})) );
-		fn = Luan.getBinHandler("__lt",o1,o2);
-		if( fn != null )
-			return !Luan.checkBoolean( Luan.first(fn.call(luan,new Object[]{o2,o1})) );
-		throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) );
-	}
-}
--- a/core/src/luan/impl/LenExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanTable;
-import luan.LuanFunction;
-import luan.LuanException;
-
-
-final class LenExpr extends UnaryOpExpr {
-
-	LenExpr(Expr op) {
-		super(op);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		Object o = op.eval(luan);
-		if( o instanceof String ) {
-			String s = (String)o;
-			return s.length();
-		}
-		if( o instanceof byte[] ) {
-			byte[] a = (byte[])o;
-			return a.length;
-		}
-		if( !(o instanceof LuanTable) )
-			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/LtExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanFunction;
-import luan.LuanException;
-
-
-final class LtExpr extends BinaryOpExpr {
-
-	LtExpr(Expr op1,Expr op2) {
-		super(op1,op2);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		Object o1 = op1.eval(luan);
-		Object o2 = op2.eval(luan);
-		return Luan.isLessThan(luan,o1,o2);
-	}
-}
--- a/core/src/luan/impl/LuanCompiler.java	Tue Apr 12 14:44:10 2016 -0600
+++ b/core/src/luan/impl/LuanCompiler.java	Tue Apr 12 17:03:30 2016 -0600
@@ -6,6 +6,7 @@
 import luan.LuanState;
 import luan.LuanException;
 import luan.LuanTable;
+import luan.LuanJava;
 import luan.modules.JavaLuan;
 import luan.modules.PackageLuan;
 
@@ -15,14 +16,23 @@
 
 	public static LuanFunction compile(LuanState luan,String sourceName,String sourceText,LuanTable env,boolean allowExpr) throws LuanException {
 		LuanParser parser = new LuanParser(sourceName,sourceText);
-		parser.addVar( env!=null ? "_ENV" : null );
 		parser.addVar( "java" );
 		parser.addVar( "require" );
+		if( env != null )  parser.addVar( "_ENV" );
 		Class fnClass = parse(parser,allowExpr);
-		final LuanStateImpl luanImpl = (LuanStateImpl)luan;
+		LuanJava java;
+		if( env == null ) {
+			java = new LuanJava();
+		} else {
+			java = env.java;
+			if( java == null ) {
+				java = new LuanJava();
+				env.java = java;
+			}
+		}
 		Closure closure;
 		try {
-			closure = (Closure)fnClass.getConstructor(LuanState.class).newInstance(luanImpl);
+			closure = (Closure)fnClass.getConstructor(LuanState.class,LuanJava.class).newInstance(luan,java);
 		} catch(NoSuchMethodException e) {
 			throw new RuntimeException(e);
 		} catch(InstantiationException e) {
@@ -32,9 +42,9 @@
 		} catch(InvocationTargetException e) {
 			throw new RuntimeException(e);
 		}
-		closure.upValues[0].o = env!=null ? env : new LuanTable();
-		closure.upValues[1].o = JavaLuan.javaFn;
-		closure.upValues[2].o = PackageLuan.requireFn;
+		closure.upValues[0].o = JavaLuan.javaFn;
+		closure.upValues[1].o = PackageLuan.requireFn;
+		if( env != null )  closure.upValues[2].o = env;
 		return closure;
 	}
 
@@ -51,8 +61,4 @@
 			throw new LuanException( e.getFancyMessage() );
 		}
 	}
-
-	public static LuanState newLuanState() {
-		return new LuanStateImpl();
-	}
 }
--- a/core/src/luan/impl/LuanImpl.java	Tue Apr 12 14:44:10 2016 -0600
+++ b/core/src/luan/impl/LuanImpl.java	Tue Apr 12 17:03:30 2016 -0600
@@ -170,29 +170,13 @@
 
 	public static void nop(Object o) {}
 
-/*
-	public static void set(LuanStateImpl luan,Settable[] vars,Object obj) throws LuanException {
-		if( obj instanceof Object[] ) {
-			Object[] vals = (Object[])obj;
-			for( int i=0; i<vars.length; i++ ) {
-				Object val = i < vals.length ? vals[i] : null;
-				vars[i].set(luan,val);
-			}
-		} else {
-			vars[0].set(luan,obj);
-			for( int i=1; i<vars.length; i++ ) {
-				vars[i].set(luan,null);
-			}
-		}
-	}
-*/
 	public static void put(LuanState luan,Object t,Object key,Object value) throws LuanException {
 		if( t instanceof LuanTable ) {
 			LuanTable tbl = (LuanTable)t;
 			tbl.put(luan,key,value);
 			return;
 		}
-		if( t != null && luan.hasJava() )
+		if( t != null && luan.java.ok )
 			JavaLuan.__new_index(luan,t,key,value);
 		else
 			throw new LuanException( "attempt to index a " + Luan.type(t) + " value" );
--- a/core/src/luan/impl/LuanParser.java	Tue Apr 12 14:44:10 2016 -0600
+++ b/core/src/luan/impl/LuanParser.java	Tue Apr 12 17:03:30 2016 -0600
@@ -240,7 +240,7 @@
 			throw parser.exception(msg);
 		return t;
 	}
-
+/*
 	private static Expr expr(Expressions exprs) {
 		if( exprs==null )
 			return null;
@@ -248,7 +248,7 @@
 			return (Expr)exprs; 
 		return new ExpressionsExpr(exprs);
 	}
-
+*/
 	private Class newFnClass(int start,StmtString stmt) {
 		if( !stmt.hasReturn )
 			stmt.list.add( "return LuanFunction.NOTHING;\n" );
@@ -1854,12 +1854,13 @@
 			+"import luan.Luan;\n"
 			+"import luan.LuanFunction;\n"
 			+"import luan.LuanState;\n"
+			+"import luan.LuanJava;\n"
 			+"import luan.LuanException;\n"
 			+"import luan.modules.PackageLuan;\n"
 			+"\n"
 			+"public class " + className +" extends Closure {\n"
-			+"	public "+className+"(LuanState luan) throws LuanException {\n"
-			+"		super("+upValueSymbols.size()+");\n"
+			+"	public "+className+"(LuanState luan,LuanJava java) throws LuanException {\n"
+			+"		super("+upValueSymbols.size()+",java);\n"
 			+		init(upValueSymbols)
 			+"	}\n"
 			+"\n"
@@ -1882,7 +1883,7 @@
 		ExpString exp = new ExpString(true,false);
 		exp.list.add( ""
 			+"\n"
-			+"new Closure("+upValueSymbols.size()+") {\n"
+			+"new Closure("+upValueSymbols.size()+",java) {\n"
 			+"{\n"
 			+ init(upValueSymbols)
 			+"}\n"
--- a/core/src/luan/impl/LuanStateImpl.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-package luan.impl;
-
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.HashMap;
-import luan.Luan;
-import luan.LuanState;
-import luan.LuanTable;
-import luan.LuanFunction;
-import luan.LuanException;
-import luan.DeepCloner;
-
-
-public final class LuanStateImpl extends LuanState {
-	Closure closure;
-
-	LuanStateImpl() {}
-
-	private LuanStateImpl(LuanStateImpl luan) {
-		super(luan);
-	}
-
-	@Override public LuanState shallowClone() {
-		return new LuanStateImpl(this);
-	}
-
-	@Override public boolean hasJava() {
-		if( closure==null )
-			return false;
-		return ((LuanTable)closure.upValues[0].o).hasJava;
-	}
-
-	@Override public void setJava() {
-		((LuanTable)closure.upValues[0].o).hasJava = true;
-	}
-
-}
--- a/core/src/luan/impl/ModExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-
-
-final class ModExpr extends BinaryOpExpr {
-
-	ModExpr(Expr op1,Expr op2) {
-		super(op1,op2);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		Object o1 = op1.eval(luan);
-		Object o2 = op2.eval(luan);
-		if( o1 instanceof Number && o2 instanceof Number ) {
-			double d1 = ((Number)o1).doubleValue();
-			double d2 = ((Number)o2).doubleValue();
-			return d1 - Math.floor(d1/d2)*d2;
-		}
-		return arithmetic(luan,"__mod",o1,o2);
-	}
-}
--- a/core/src/luan/impl/MulExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-
-
-final class MulExpr extends BinaryOpExpr {
-
-	MulExpr(Expr op1,Expr op2) {
-		super(op1,op2);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		Object o1 = op1.eval(luan);
-		Object o2 = op2.eval(luan);
-		if( o1 instanceof Number && o2 instanceof Number )
-			return ((Number)o1).doubleValue() * ((Number)o2).doubleValue();
-		return arithmetic(luan,"__mul",o1,o2);
-	}
-}
--- a/core/src/luan/impl/NotExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanException;
-
-
-final class NotExpr extends UnaryOpExpr {
-
-	NotExpr(Expr op) {
-		super(op);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		return !Luan.checkBoolean( op.eval(luan) );
-	}
-
-	@Override public String toString() {
-		return "(NotExpr "+op+")";
-	}
-}
--- a/core/src/luan/impl/OrExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanException;
-
-
-final class OrExpr extends BinaryOpExpr implements StmtExp {
-
-	OrExpr(Expr op1,Expr op2) {
-		super(op1,op2);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		Object v1 = op1.eval(luan);
-		return v1 != null && !Boolean.FALSE.equals(v1) ? v1 : op2.eval(luan);
-	}
-}
--- a/core/src/luan/impl/PowExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-
-
-final class PowExpr extends BinaryOpExpr {
-
-	PowExpr(Expr op1,Expr op2) {
-		super(op1,op2);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		Object o1 = op1.eval(luan);
-		Object o2 = op2.eval(luan);
-		if( o1 instanceof Number && o2 instanceof Number )
-			return Math.pow( ((Number)o1).doubleValue(), ((Number)o2).doubleValue() );
-		return arithmetic(luan,"__pow",o1,o2);
-	}
-}
--- a/core/src/luan/impl/RepeatStmt.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanException;
-
-
-final class RepeatStmt extends CodeImpl implements Stmt {
-	private final Stmt doStmt;
-	private final Expr cnd;
-
-	RepeatStmt(Stmt doStmt,Expr cnd) {
-		this.doStmt = doStmt;
-		this.cnd = cnd;
-	}
-
-	@Override public void eval(LuanStateImpl luan) throws LuanException {
-		try {
-			do {
-				doStmt.eval(luan);
-			} while( !Luan.checkBoolean( cnd.eval(luan) ) );
-		} catch(BreakException e) {}
-	}
-}
--- a/core/src/luan/impl/ReturnStmt.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanException;
-import luan.LuanFunction;
-
-
-final class ReturnStmt extends CodeImpl implements Stmt {
-	private final Expressions expressions;
-	boolean throwReturnException = true;
-
-	ReturnStmt(Expressions expressions) {
-		this.expressions = expressions;
-	}
-
-	@Override public void eval(LuanStateImpl luan) throws LuanException {
-//		luan.returnValues = expressions.eval(luan);
-		if( throwReturnException )
-			throw new ReturnException();
-	}
-}
--- a/core/src/luan/impl/SetStmt.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanException;
-
-
-final class SetStmt implements Stmt {
-	private final Settable[] vars;
-	private final Expressions expressions;
-
-	SetStmt(Settable var,Expr expr) {
-		this( new Settable[]{var}, expr );
-	}
-
-	SetStmt(Settable[] vars,Expressions expressions) {
-		this.vars = vars;
-		this.expressions = expressions;
-	}
-
-	@Override public void eval(LuanStateImpl luan) throws LuanException {
-		final Object obj = expressions.eval(luan);
-		if( obj instanceof Object[] ) {
-			Object[] vals = (Object[])obj;
-			for( int i=0; i<vars.length; i++ ) {
-				Object val = i < vals.length ? vals[i] : null;
-				vars[i].set(luan,val);
-			}
-		} else {
-			vars[0].set(luan,obj);
-			for( int i=1; i<vars.length; i++ ) {
-				vars[i].set(luan,null);
-			}
-		}
-	}
-
-}
--- a/core/src/luan/impl/SetTableEntry.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-import luan.LuanTable;
-import luan.Luan;
-import luan.LuanFunction;
-import luan.LuanMeta;
-import luan.modules.JavaLuan;
-
-
-final class SetTableEntry extends CodeImpl implements Settable {
-	private final Expr tableExpr;
-	private final Expr keyExpr;
-
-	SetTableEntry(Expr tableExpr,Expr keyExpr) {
-		this.tableExpr = tableExpr;
-		this.keyExpr = keyExpr;
-	}
-
-	@Override public void set(LuanStateImpl luan,Object value) throws LuanException {
-		newIndex( luan, tableExpr.eval(luan), keyExpr.eval(luan), value );
-	}
-
-	private void newIndex(LuanStateImpl luan,Object t,Object key,Object value) throws LuanException {
-		if( t instanceof LuanTable ) {
-			LuanTable tbl = (LuanTable)t;
-			tbl.put(luan,key,value);
-			return;
-		}
-		if( t != null && luan.hasJava() )
-			JavaLuan.__new_index(luan,t,key,value);
-		else
-			throw new LuanException( "attempt to index a " + Luan.type(t) + " value" );
-	}
-
-}
--- a/core/src/luan/impl/Settable.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-
-
-public interface Settable {
-	public void set(LuanStateImpl luan,Object value) throws LuanException;
-}
--- a/core/src/luan/impl/Stmt.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-
-
-public interface Stmt {
-	public void eval(LuanStateImpl luan) throws LuanException;
-
-	static final Stmt EMPTY = new Stmt() {
-		@Override public void eval(LuanStateImpl luan) {}
-	};
-}
--- a/core/src/luan/impl/StmtExp.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-
-
-public interface StmtExp extends Expressions {}
--- a/core/src/luan/impl/SubExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-
-
-final class SubExpr extends BinaryOpExpr {
-
-	SubExpr(Expr op1,Expr op2) {
-		super(op1,op2);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		Object o1 = op1.eval(luan);
-		Object o2 = op2.eval(luan);
-		if( o1 instanceof Number && o2 instanceof Number )
-			return ((Number)o1).doubleValue() - ((Number)o2).doubleValue();
-		return arithmetic(luan,"__sub",o1,o2);
-	}
-}
--- a/core/src/luan/impl/TableExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-import luan.LuanTable;
-import luan.Luan;
-
-
-final class TableExpr extends CodeImpl implements Expr {
-
-	static class Field {
-		final Expr key;
-		final Expr value;
-
-		Field(Expr key,Expr value) {
-			this.key = key;
-			this.value = value;
-		}
-	}
-
-	private final Field[] fields;
-	private final Expressions expressions;
-
-	TableExpr(Field[] fields,Expressions expressions) {
-		this.fields = fields;
-		this.expressions = expressions;
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		LuanTable table = new LuanTable();
-		for( Field field : fields ) {
-			table.rawPut( field.key.eval(luan), field.value.eval(luan) );
-		}
-		Object obj = expressions.eval(luan);
-		if( obj instanceof Object[] ) {
-			Object[] a = (Object[])obj;
-			for( int i=0; i<a.length; i++ ) {
-				table.rawPut( i+1, a[i] );
-			}
-		} else {
-			table.rawPut( 1, obj );
-		}
-		return table;
-	}
-}
--- a/core/src/luan/impl/UnaryOpExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-package luan.impl;
-
-
-abstract class UnaryOpExpr extends CodeImpl implements Expr {
-	final Expr op;
-
-	UnaryOpExpr(Expr op) {
-		this.op = op;
-	}
-}
--- a/core/src/luan/impl/UnmExpr.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanFunction;
-import luan.LuanException;
-import luan.LuanTable;
-
-
-// unary minus
-final class UnmExpr extends UnaryOpExpr {
-
-	UnmExpr(Expr op) {
-		super(op);
-	}
-
-	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		Object o = op.eval(luan);
-		if( o instanceof Number )
-			return -((Number)o).doubleValue();
-		if( o instanceof LuanTable ) {
-			LuanFunction fn = Luan.getHandlerFunction("__unm",(LuanTable)o);
-			if( fn != null ) {
-				return Luan.first(fn.call(luan,new Object[]{o}));
-			}
-		}
-		throw new LuanException("attempt to perform arithmetic on a "+Luan.type(o)+" value");
-	}
-}
--- a/core/src/luan/impl/WhileStmt.java	Tue Apr 12 14:44:10 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanException;
-
-
-final class WhileStmt extends CodeImpl implements Stmt {
-	private final Expr cnd;
-	private final Stmt doStmt;
-
-	WhileStmt(Expr cnd,Stmt doStmt) {
-		this.cnd = cnd;
-		this.doStmt = doStmt;
-	}
-
-	@Override public void eval(LuanStateImpl luan) throws LuanException {
-		try {
-			while( Luan.checkBoolean( cnd.eval(luan) ) ) {
-				doStmt.eval(luan);
-			}
-		} catch(BreakException e) {}
-	}
-}
--- a/core/src/luan/modules/JavaLuan.java	Tue Apr 12 14:44:10 2016 -0600
+++ b/core/src/luan/modules/JavaLuan.java	Tue Apr 12 17:03:30 2016 -0600
@@ -28,7 +28,7 @@
 
 	public static void java(LuanState luan) throws LuanException {
 		check(luan,"fix later");
-		luan.setJava();
+		luan.java.ok = true;
 	}
 
 	public static final LuanFunction javaFn;
@@ -41,7 +41,7 @@
 	}
 
 	private static void checkJava(LuanState luan) throws LuanException {
-		if( !luan.hasJava() )
+		if( !luan.java.ok )
 			throw new LuanException("Java isn't allowed");
 	}