view core/src/luan/LuanBit.java @ 575:7c3ad6db8ac3

make LuanState.JAVA private
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 13 Jul 2015 18:34:31 -0600
parents 6cc2f047019b
children
line wrap: on
line source

package luan;

import java.util.List;


public final class LuanBit {
	public final LuanState luan;
	public final LuanElement el;

	LuanBit(LuanState luan,LuanElement el) {
		this.luan = luan;
		this.el = el;
	}

	public LuanException exception(Object msg) throws LuanException {
		return new LuanException(this,msg);
	}

	public StackTraceElement[] stackTrace() {
		List<StackTraceElement> stackTrace = luan.stackTrace;
		if( el != null )
			stackTrace.add(new StackTraceElement(el,null));
		StackTraceElement[] rtn = stackTrace.toArray(new StackTraceElement[0]);
		if( el != null )
			stackTrace.remove(stackTrace.size()-1);
		return rtn;
	}

	public void dumpStack() {
		System.err.println( stackTrace() );
	}

	public Object call(LuanFunction fn,String fnName,Object[] args) throws LuanException {
		push(fnName);
		try {
			return fn.call(luan,args);
		} catch(StackOverflowError e) {
			throw exception("stack overflow");
		} finally {
			pop();
		}
	}

	private void push(String fnName) {
		if( el == null )  throw new RuntimeException();
		List<StackTraceElement> stackTrace = luan.stackTrace;
		stackTrace.add( new StackTraceElement(el,fnName) );
	}

	private void pop() {
		List<StackTraceElement> stackTrace = luan.stackTrace;
		stackTrace.remove(stackTrace.size()-1);
	}

	public String toString(Object obj) throws LuanException {
		push(null);
		try {
			return luan.toString(obj);
		} finally {
			pop();
		}
	}

	public Object index(Object obj,Object key) throws LuanException {
		push(null);
		try {
			return luan.index(obj,key);
		} finally {
			pop();
		}
	}

	public int length(LuanTable t) throws LuanException {
		push(null);
		try {
			return t.length(luan);
		} finally {
			pop();
		}
	}

	public void put(LuanTable t,Object key,Object value) throws LuanException {
		push(null);
		try {
			t.put(luan,key,value);
		} finally {
			pop();
		}
	}

	public String checkString(Object obj) throws LuanException {
		if( obj instanceof String )
			return (String)obj;
		if( el != null ) {
			throw exception( "attempt to use '"+el.text()+"' (a " + Luan.type(obj) + " value) as a string" );
		} else {
			throw exception( "attempt to use a " + Luan.type(obj) + " as a string" );
		}
	}

	public Number checkNumber(Object obj) throws LuanException {
		if( obj instanceof Number )
			return (Number)obj;
		if( el != null ) {
			throw exception( "attempt to perform arithmetic on '"+el.text()+"' (a " + Luan.type(obj) + " value)" );
		} else {
			throw exception( "attempt to perform arithmetic on a " + Luan.type(obj) + " value" );
		}
	}

	public LuanFunction checkFunction(Object obj) throws LuanException {
		if( obj instanceof LuanFunction )
			return (LuanFunction)obj;
		if( el != null ) {
			throw exception( "attempt to call '"+el.text()+"' (a " + Luan.type(obj) + " value)" );
		} else {
			throw exception( "attempt to call a " + Luan.type(obj) + " value" );
		}
	}

	public Boolean checkBoolean(Object obj) throws LuanException {
		if( obj instanceof Boolean )
			return (Boolean)obj;
		if( el != null ) {
			throw exception( "attempt to use '"+el.text()+"' (a " + Luan.type(obj) + " value) as a boolean" );
		} else {
			throw exception( "attempt to use a " + Luan.type(obj) + " as a boolean" );
		}
	}

	public LuanFunction getHandlerFunction(String op,LuanTable t) throws LuanException {
		Object f = t.getHandler(op);
		if( f == null )
			return null;
		return checkFunction(f);
	}

	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 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 checkBoolean( Luan.first(call(fn,"__lt",new Object[]{o1,o2})) );
		throw exception( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) );
	}

	public Object arithmetic(String op,Object o1,Object o2) throws LuanException {
		LuanFunction fn = getBinHandler(op,o1,o2);
		if( fn != null )
			return Luan.first(call(fn,op,new Object[]{o1,o2}));
		String type = !(o1 instanceof Number) ? Luan.type(o1) : Luan.type(o2);
		throw exception("attempt to perform arithmetic on a "+type+" value");
	}

}