view src/luan/LuanState.java @ 1202:d3a3ca116e42

gc site instances
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 05 Mar 2018 19:30:51 -0700
parents 7ef40e1923b7
children cb422386f6b5
line wrap: on
line source

package luan;

import java.io.Closeable;
import java.io.IOException;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import luan.impl.LuanCompiler;
import luan.modules.BasicLuan;
import luan.modules.JavaLuan;


public final class LuanState implements LuanCloneable {
	public LuanJavaOk javaOk;
	private Map registry;
	private final List<Reference<Closeable>> onClose = new ArrayList<Reference<Closeable>>();
	public boolean isLocked = false;

	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) {
		onClose.add(new WeakReference<Closeable>(c));
	}

	public void close() throws IOException {
		for( Reference<Closeable> ref : onClose ) {
			Closeable c = ref.get();
			if( c != null )
				c.close();
		}
		onClose.clear();
	}

	protected void finalize() throws Throwable {
		close();
	}

	public final Object eval(String cmd,Object... args) throws LuanException {
		return Luan.load(cmd,"eval").call(this,args);
	}
/*
	public final Object eval(String cmd,LuanTable env) throws LuanException {
		LuanFunction fn = BasicLuan.load(this,cmd,"eval",env,true);
		return fn.call(this);
	}
*/

	public String toString(Object obj) throws LuanException {
		if( obj instanceof LuanTable ) {
			LuanTable tbl = (LuanTable)obj;
			return tbl.toString(this);
		}
		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(this,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(this,op);
		if( f == null )
			return null;
		return Luan.checkFunction(f);
	}
}