view src/luan/LuanState.java @ 1283:503bde9a7c80

add luan.require() and table.call()
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 21 Dec 2018 09:12:09 -0700
parents 9fa8b8389578
children f41919741100
line wrap: on
line source

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);

	public LuanJavaOk javaOk;
	private Map registry;
	public boolean isLocked = false;

	public interface OnClose extends Closeable {
		public void onClose(Closeable c);
	}
	public OnClose onClose;

	public LuanState() {
		javaOk = new LuanJavaOk();
		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);
		clone.javaOk = (LuanJavaOk)cloner.clone(javaOk);
		if( cloner.type == LuanCloner.Type.INCREMENTAL )
			isLocked = true;
	}

	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 && javaOk.ok )
			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;
	}

}