diff src/luan/Luan.java @ 1333:25746915a241

merge Luan and LuanState
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 12 Feb 2019 22:33:40 -0700
parents f41919741100
children c88b486a9511
line wrap: on
line diff
--- 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
 }