changeset 404:d55e873e1f0d

metatables now only apply to tables
author Franklin Schmidt <fschmidt@gmail.com>
date Wed, 29 Apr 2015 07:04:40 -0600
parents 637f7ad85654
children 3e68917a0dc6
files core/src/luan/LuanBit.java core/src/luan/LuanState.java core/src/luan/impl/EqExpr.java core/src/luan/impl/FnCall.java core/src/luan/impl/IndexExpr.java core/src/luan/impl/LenExpr.java core/src/luan/impl/SetTableEntry.java core/src/luan/impl/UnmExpr.java core/src/luan/modules/BasicLuan.java core/src/luan/modules/BinaryLuan.java core/src/luan/modules/JavaLuan.java core/src/luan/modules/StringLuan.java
diffstat 12 files changed, 103 insertions(+), 140 deletions(-) [+]
line wrap: on
line diff
--- a/core/src/luan/LuanBit.java	Tue Apr 28 22:49:33 2015 -0600
+++ b/core/src/luan/LuanBit.java	Wed Apr 29 07:04:40 2015 -0600
@@ -88,34 +88,40 @@
 	}
 
 	public String toString(Object obj) throws LuanException {
-		LuanFunction fn = getHandlerFunction("__tostring",obj);
-		if( fn != null )
-			return checkString( Luan.first( call(fn,"__tostring",new Object[]{obj}) ) );
+		if( obj instanceof LuanTable ) {
+			LuanFunction fn = getHandlerFunction("__tostring",(LuanTable)obj);
+			if( fn != null )
+				return checkString( Luan.first( call(fn,"__tostring",new Object[]{obj}) ) );
+		}
 		return Luan.toString(obj);
 	}
 
 	public String repr(Object obj) throws LuanException {
-		LuanFunction fn = getHandlerFunction("__repr",obj);
-		if( fn != null )
-			return checkString( Luan.first( call(fn,"__repr",new Object[]{obj}) ) );
+		if( obj instanceof LuanTable ) {
+			LuanFunction fn = getHandlerFunction("__repr",(LuanTable)obj);
+			if( fn != null )
+				return checkString( Luan.first( call(fn,"__repr",new Object[]{obj}) ) );
+		}
 		String repr = Luan.repr(obj);
 		if( repr==null )
 			throw exception( "value '" + obj + "' doesn't support repr()" );
 		return repr;
 	}
 
-	public LuanFunction getHandlerFunction(String op,Object obj) throws LuanException {
-		Object f = luan.getHandler(op,obj);
+	public LuanFunction getHandlerFunction(String op,LuanTable t) throws LuanException {
+		Object f = luan.getHandler(op,t);
 		if( f == null )
 			return null;
 		return checkFunction(f);
 	}
 
 	public LuanFunction getBinHandler(String op,Object o1,Object o2) throws LuanException {
-		LuanFunction f1 = getHandlerFunction(op,o1);
-		if( f1 != null )
-			return f1;
-		return getHandlerFunction(op,o2);
+		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 {
--- a/core/src/luan/LuanState.java	Tue Apr 28 22:49:33 2015 -0600
+++ b/core/src/luan/LuanState.java	Wed Apr 29 07:04:40 2015 -0600
@@ -21,18 +21,15 @@
 	final List<StackTraceElement> stackTrace = new ArrayList<StackTraceElement>();
 
 	private LuanTableImpl registry;
-	private LuanTableImpl metatable;  // generic metatable
 
 	protected LuanState() {
 		registry = new LuanTableImpl();
-		metatable = newMetatable();
 	}
 
 	protected LuanState(LuanState luan) {}
 
 	@Override public void deepenClone(LuanState clone,DeepCloner cloner) {
 		clone.registry = cloner.deepClone(registry);
-		clone.metatable = cloner.deepClone(metatable);
 	}
 
 	public abstract LuanTable currentEnvironment();
@@ -59,63 +56,15 @@
 		return call(fn);
 	}
 
-	public final LuanTable getMetatable(Object obj) {
-		if( obj==null )
-			return null;
-		if( obj instanceof LuanTable ) {
-			LuanTable table = (LuanTable)obj;
-			return table.getMetatable();
-		}
-		return metatable;
-	}
-
 	public final LuanBit bit(LuanElement el) {
 		return new LuanBit(this,el);
 	}
 
-	public final Object getHandler(String op,Object obj) {
-		LuanTable t = getMetatable(obj);
-		return t==null ? null : t.get(op);
-	}
-
-	public final Object getHandler(String op,LuanTable table) {
+	public final static Object getHandler(String op,LuanTable table) {
 		LuanTable t = table.getMetatable();
 		return t==null ? null : t.get(op);
 	}
 
-	private static LuanTableImpl newMetatable() {
-		LuanTableImpl metatable = new LuanTableImpl();
-		try {
-			metatable.put( "__index", new LuanJavaFunction(
-				LuanState.class.getMethod("__index",LuanState.class,Object.class,Object.class), null
-			) );
-			metatable.put( "__newindex", new LuanJavaFunction(
-				LuanState.class.getMethod("__newindex",LuanState.class,Object.class,Object.class,Object.class), null
-			) );
-		} catch(NoSuchMethodException e) {
-			throw new RuntimeException(e);
-		}
-		return metatable;
-	}
-
-	public static Object __index(LuanState luan,Object obj,Object key) throws LuanException {
-		if( obj instanceof String ) {
-			Object rtn = StringLuan.__index(luan,(String)obj,key);
-			if( rtn != null )
-				return rtn;
-		}
-		if( obj instanceof byte[] ) {
-			Object rtn = BinaryLuan.__index(luan,(byte[])obj,key);
-			if( rtn != null )
-				return rtn;
-		}
-		return JavaLuan.__index(luan,obj,key);
-	}
-
-	public static void __newindex(LuanState luan,Object obj,Object key,Object value) throws LuanException {
-		JavaLuan.__newindex(luan,obj,key,value);
-	}
-
 	// convenience methods
 
 	private final LuanBit JAVA = bit(LuanElement.JAVA);
--- a/core/src/luan/impl/EqExpr.java	Tue Apr 28 22:49:33 2015 -0600
+++ b/core/src/luan/impl/EqExpr.java	Wed Apr 29 07:04:40 2015 -0600
@@ -34,10 +34,12 @@
 			byte[] b2 = (byte[])o2;
 			return Arrays.equals(b1,b2);
 		}
-		if( o1==null || o2==null || !o1.getClass().equals(o2.getClass()) )
+		if( !(o1 instanceof LuanTable && o2 instanceof LuanTable) )
 			return false;
-		LuanTable mt1 = luan.getMetatable(o1);
-		LuanTable mt2 = luan.getMetatable(o2);
+		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.get("__eq");
--- a/core/src/luan/impl/FnCall.java	Tue Apr 28 22:49:33 2015 -0600
+++ b/core/src/luan/impl/FnCall.java	Wed Apr 29 07:04:40 2015 -0600
@@ -4,6 +4,7 @@
 import luan.LuanFunction;
 import luan.LuanException;
 import luan.LuanSource;
+import luan.LuanTable;
 
 
 final class FnCall extends CodeImpl implements Expressions {
@@ -27,9 +28,11 @@
 			LuanFunction fn = (LuanFunction)o;
 			return luan.bit(se).call( fn, fnName, Luan.array(args.eval(luan)) );
 		}
-		Object h = luan.getHandler("__call",o);
-		if( h != null )
-			return call(luan,h);
+		if( o instanceof LuanTable ) {
+			Object h = luan.getHandler("__call",(LuanTable)o);
+			if( h != null )
+				return call(luan,h);
+		}
 		throw luan.bit(fnExpr.se()).exception( "attempt to call '"+fnExpr.se().text()+"' (a " + Luan.type(o) + " value)" );
 	}
 
--- a/core/src/luan/impl/IndexExpr.java	Tue Apr 28 22:49:33 2015 -0600
+++ b/core/src/luan/impl/IndexExpr.java	Wed Apr 29 07:04:40 2015 -0600
@@ -5,6 +5,9 @@
 import luan.LuanTable;
 import luan.LuanFunction;
 import luan.LuanSource;
+import luan.modules.StringLuan;
+import luan.modules.BinaryLuan;
+import luan.modules.JavaLuan;
 
 
 final class IndexExpr extends BinaryOpExpr {
@@ -17,25 +20,28 @@
 		return index(luan,op1.eval(luan),op2.eval(luan));
 	}
 
-	private Object index(LuanStateImpl luan,Object t,Object key) throws LuanException {
-		Object h;
-		if( t instanceof LuanTable ) {
-			LuanTable tbl = (LuanTable)t;
+	private Object index(LuanStateImpl luan,Object obj,Object key) throws LuanException {
+		if( obj instanceof LuanTable ) {
+			LuanTable tbl = (LuanTable)obj;
 			Object value = tbl.get(key);
 			if( value != null )
 				return value;
-			h = luan.getHandler("__index",t);
+			Object h = luan.getHandler("__index",tbl);
 			if( h==null )
 				return null;
-		} else {
-			h = luan.getHandler("__index",t);
-			if( h==null )
-				throw luan.bit(op1.se()).exception( "attempt to index '"+op1.se().text()+"' (a " + Luan.type(t) + " value)" );
+			if( h instanceof LuanFunction ) {
+				LuanFunction fn = (LuanFunction)h;
+				return Luan.first(luan.bit(se).call(fn,"__index",new Object[]{tbl,key}));
+			}
+			return index(luan,h,key);
 		}
-		if( h instanceof LuanFunction ) {
-			LuanFunction fn = (LuanFunction)h;
-			return Luan.first(luan.bit(se).call(fn,"__index",new Object[]{t,key}));
-		}
-		return index(luan,h,key);
+		if( obj instanceof String )
+			return StringLuan.__index(luan,(String)obj,key);
+		if( obj instanceof byte[] )
+			return BinaryLuan.__index(luan,(byte[])obj,key);
+		Object value = JavaLuan.__index(luan,obj,key);
+		if( value != null )
+			return value;
+		throw luan.bit(op1.se()).exception( "attempt to index '"+op1.se().text()+"' (a " + Luan.type(obj) + " value)" );
 	}
 }
--- a/core/src/luan/impl/LenExpr.java	Tue Apr 28 22:49:33 2015 -0600
+++ b/core/src/luan/impl/LenExpr.java	Wed Apr 29 07:04:40 2015 -0600
@@ -25,13 +25,12 @@
 			return a.length;
 		}
 		LuanBit bit = luan.bit(se);
-		LuanFunction fn = bit.getHandlerFunction("__len",o);
+		if( !(o instanceof LuanTable) )
+			throw bit.exception( "attempt to get length of a " + Luan.type(o) + " value" );
+		LuanTable t = (LuanTable)o;
+		LuanFunction fn = bit.getHandlerFunction("__len",t);
 		if( fn != null )
 			return Luan.first(bit.call(fn,"__len",new Object[]{o}));
-		if( o instanceof LuanTable ) {
-			LuanTable t = (LuanTable)o;
-			return t.length();
-		}
-		throw bit.exception( "attempt to get length of a " + Luan.type(o) + " value" );
+		return t.length();
 	}
 }
--- a/core/src/luan/impl/SetTableEntry.java	Tue Apr 28 22:49:33 2015 -0600
+++ b/core/src/luan/impl/SetTableEntry.java	Wed Apr 29 07:04:40 2015 -0600
@@ -5,6 +5,7 @@
 import luan.Luan;
 import luan.LuanFunction;
 import luan.LuanSource;
+import luan.modules.JavaLuan;
 
 
 final class SetTableEntry extends CodeImpl implements Settable {
@@ -22,10 +23,9 @@
 	}
 
 	private void newindex(LuanStateImpl luan,Object t,Object key,Object value) throws LuanException {
-		Object h;
 		if( t instanceof LuanTable ) {
 			LuanTable table = (LuanTable)t;
-			h = luan.getHandler("__newindex",table);
+			Object h = luan.getHandler("__newindex",table);
 			if( h==null || table.get(key)!=null ) {
 				try {
 					table.put(key,value);
@@ -36,17 +36,15 @@
 				}
 				return;
 			}
-		} else {
-			h = luan.getHandler("__newindex",t);
-			if( h==null )
-				throw luan.bit(se).exception( "attempt to index '"+tableExpr.se().text()+"' (a " + Luan.type(t) + " value)" );
+			if( h instanceof LuanFunction ) {
+				LuanFunction fn = (LuanFunction)h;
+				luan.bit(se).call(fn,"__newindex",new Object[]{t,key,value});
+				return;
+			}
+			newindex(luan,h,key,value);
 		}
-		if( h instanceof LuanFunction ) {
-			LuanFunction fn = (LuanFunction)h;
-			luan.bit(se).call(fn,"__newindex",new Object[]{t,key,value});
-			return;
-		}
-		newindex(luan,h,key,value);
+		if( !JavaLuan.__newindex(luan,t,key,value) )
+			throw luan.bit(se).exception( "attempt to index '"+tableExpr.se().text()+"' (a " + Luan.type(t) + " value)" );
 	}
 
 }
--- a/core/src/luan/impl/UnmExpr.java	Tue Apr 28 22:49:33 2015 -0600
+++ b/core/src/luan/impl/UnmExpr.java	Wed Apr 29 07:04:40 2015 -0600
@@ -5,6 +5,7 @@
 import luan.LuanException;
 import luan.LuanSource;
 import luan.LuanBit;
+import luan.LuanTable;
 
 
 // unary minus
@@ -20,9 +21,11 @@
 		if( n != null )
 			return -n.doubleValue();
 		LuanBit bit = luan.bit(se);
-		LuanFunction fn = bit.getHandlerFunction("__unm",o);
-		if( fn != null ) {
-			return Luan.first(bit.call(fn,"__unm",new Object[]{o}));
+		if( o instanceof LuanTable ) {
+			LuanFunction fn = bit.getHandlerFunction("__unm",(LuanTable)o);
+			if( fn != null ) {
+				return Luan.first(bit.call(fn,"__unm",new Object[]{o}));
+			}
 		}
 		throw bit.exception("attempt to perform arithmetic on a "+Luan.type(o)+" value");
 	}
--- a/core/src/luan/modules/BasicLuan.java	Tue Apr 28 22:49:33 2015 -0600
+++ b/core/src/luan/modules/BasicLuan.java	Wed Apr 29 07:04:40 2015 -0600
@@ -77,8 +77,8 @@
 		};
 	}
 
-	public static LuanTable get_metatable(LuanState luan,Object obj) {
-		return luan.getMetatable(obj);
+	public static LuanTable get_metatable(LuanTable table) {
+		return table.getMetatable();
 	}
 
 	public static LuanTable set_metatable(LuanTable table,LuanTable metatable) {
--- a/core/src/luan/modules/BinaryLuan.java	Tue Apr 28 22:49:33 2015 -0600
+++ b/core/src/luan/modules/BinaryLuan.java	Wed Apr 29 07:04:40 2015 -0600
@@ -11,20 +11,18 @@
 public final class BinaryLuan {
 
 	public static Object __index(LuanState luan,final byte[] binary,Object key) throws LuanException {
-		LuanTable mod = (LuanTable)PackageLuan.loaded(luan).get("luan:Binary");
-		if( mod!=null ) {
-			Object obj = mod.get(key);
-			if( obj instanceof LuanFunction ) {
-				final LuanFunction fn = (LuanFunction)obj;
-				return new LuanFunction() {
-					@Override public Object call(LuanState luan,Object[] args) throws LuanException {
-						Object[] a = new Object[args.length+1];
-						a[0] = binary;
-						System.arraycopy(args,0,a,1,args.length);
-						return fn.call(luan,a);
-					}
-				};
-			}
+		LuanTable mod = (LuanTable)luan.require("luan:Binary");
+		Object obj = mod.get(key);
+		if( obj instanceof LuanFunction ) {
+			final LuanFunction fn = (LuanFunction)obj;
+			return new LuanFunction() {
+				@Override public Object call(LuanState luan,Object[] args) throws LuanException {
+					Object[] a = new Object[args.length+1];
+					a[0] = binary;
+					System.arraycopy(args,0,a,1,args.length);
+					return fn.call(luan,a);
+				}
+			};
 		}
 		return null;
 	}
--- a/core/src/luan/modules/JavaLuan.java	Tue Apr 28 22:49:33 2015 -0600
+++ b/core/src/luan/modules/JavaLuan.java	Wed Apr 29 07:04:40 2015 -0600
@@ -143,8 +143,9 @@
 		}
 	}
 
-	public static void __newindex(LuanState luan,Object obj,Object key,Object value) throws LuanException {
-		checkJava(luan);
+	public static boolean __newindex(LuanState luan,Object obj,Object key,Object value) throws LuanException {
+		if( !luan.currentEnvironment().hasJava() )
+			return false;
 		if( obj instanceof Static ) {
 			if( key instanceof String ) {
 				String name = (String)key;
@@ -155,7 +156,7 @@
 					if( members.size() != 1 )
 						throw new RuntimeException("not field '"+name+"' of "+obj);
 					setMember(obj,members,value);
-					return;
+					return true;
 				}
 			}
 			throw luan.exception("invalid member '"+key+"' for: "+obj);
@@ -165,7 +166,7 @@
 			Integer i = Luan.asInteger(key);
 			if( i != null ) {
 				Array.set(obj,i,value);
-				return;
+				return true;
 			}
 			throw luan.exception("invalid member '"+key+"' for java array: "+obj);
 		}
@@ -176,7 +177,7 @@
 				if( members.size() != 1 )
 					throw new RuntimeException("not field '"+name+"' of "+obj);
 				setMember(obj,members,value);
-				return;
+				return true;
 			}
 		}
 		throw luan.exception("invalid member '"+key+"' for java object: "+obj);
--- a/core/src/luan/modules/StringLuan.java	Tue Apr 28 22:49:33 2015 -0600
+++ b/core/src/luan/modules/StringLuan.java	Wed Apr 29 07:04:40 2015 -0600
@@ -15,20 +15,18 @@
 public final class StringLuan {
 
 	public static Object __index(LuanState luan,final String s,Object key) throws LuanException {
-		LuanTable mod = (LuanTable)PackageLuan.loaded(luan).get("luan:String");
-		if( mod!=null ) {
-			Object obj = mod.get(key);
-			if( obj instanceof LuanFunction ) {
-				final LuanFunction fn = (LuanFunction)obj;
-				return new LuanFunction() {
-					@Override public Object call(LuanState luan,Object[] args) throws LuanException {
-						Object[] a = new Object[args.length+1];
-						a[0] = s;
-						System.arraycopy(args,0,a,1,args.length);
-						return fn.call(luan,a);
-					}
-				};
-			}
+		LuanTable mod = (LuanTable)luan.require("luan:String");
+		Object obj = mod.get(key);
+		if( obj instanceof LuanFunction ) {
+			final LuanFunction fn = (LuanFunction)obj;
+			return new LuanFunction() {
+				@Override public Object call(LuanState luan,Object[] args) throws LuanException {
+					Object[] a = new Object[args.length+1];
+					a[0] = s;
+					System.arraycopy(args,0,a,1,args.length);
+					return fn.call(luan,a);
+				}
+			};
 		}
 		return null;
 	}