changeset 502:d3183a330ff5

improve the __index metamethod to work with any type; simplify luan_proxy to eliminate base;
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 19 May 2015 17:57:20 -0600
parents f26485a3692c
children 92c3d22745b8
files core/src/luan/LuanState.java core/src/luan/LuanTable.java core/src/luan/impl/IndexExpr.java core/src/luan/modules/BasicLuan.java core/src/luan/modules/JavaLuan.java website/src/manual.html.luan
diffstat 6 files changed, 48 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
diff -r f26485a3692c -r d3183a330ff5 core/src/luan/LuanState.java
--- a/core/src/luan/LuanState.java	Mon May 18 23:23:01 2015 -0600
+++ b/core/src/luan/LuanState.java	Tue May 19 17:57:20 2015 -0600
@@ -50,7 +50,7 @@
 
 	// convenience methods
 
-	private final LuanBit JAVA = bit(null);
+	final LuanBit JAVA = bit(null);
 
 	public LuanException exception(Object msg) throws LuanException {
 		return JAVA.exception(msg);
diff -r f26485a3692c -r d3183a330ff5 core/src/luan/LuanTable.java
--- a/core/src/luan/LuanTable.java	Mon May 18 23:23:01 2015 -0600
+++ b/core/src/luan/LuanTable.java	Tue May 19 17:57:20 2015 -0600
@@ -13,6 +13,9 @@
 import java.util.HashSet;
 import java.util.IdentityHashMap;
 import java.util.regex.Pattern;
+import luan.modules.StringLuan;
+import luan.modules.BinaryLuan;
+import luan.modules.JavaLuan;
 
 
 public final class LuanTable implements DeepCloneable {
@@ -120,11 +123,25 @@
 			LuanMeta meta = (LuanMeta)h;
 			return meta.__index(luan,this,key);
 		}
-		if( h instanceof LuanTable ) {
-			LuanTable tbl = (LuanTable)h;
+		return index(luan.JAVA,h,key);
+	}
+
+	public static Object index(LuanBit bit,Object obj,Object key) throws LuanException {
+		LuanState luan = bit.luan;
+		if( obj instanceof LuanTable ) {
+			LuanTable tbl = (LuanTable)obj;
 			return tbl.get(luan,key);
 		}
-		throw luan.exception("invalid type "+Luan.type(h)+" for metamethod __index");
+		if( obj instanceof String )
+			return StringLuan.__index(luan,(String)obj,key);
+		if( obj instanceof byte[] )
+			return BinaryLuan.__index(luan,(byte[])obj,key);
+		if( obj != null && luan.currentEnvironment().hasJava() )
+			return JavaLuan.__index(luan,obj,key);
+		else if( bit.el==null )
+			throw bit.exception( "attempt to index a " + Luan.type(obj) + " value" );
+		else
+			throw bit.exception( "attempt to index '"+bit.el.text()+"' (a " + Luan.type(obj) + " value)" );
 	}
 
 	public Object rawGet(Object key) {
diff -r f26485a3692c -r d3183a330ff5 core/src/luan/impl/IndexExpr.java
--- a/core/src/luan/impl/IndexExpr.java	Mon May 18 23:23:01 2015 -0600
+++ b/core/src/luan/impl/IndexExpr.java	Tue May 19 17:57:20 2015 -0600
@@ -1,14 +1,8 @@
 package luan.impl;
 
-import luan.Luan;
 import luan.LuanException;
 import luan.LuanTable;
-import luan.LuanFunction;
 import luan.LuanElement;
-import luan.LuanMeta;
-import luan.modules.StringLuan;
-import luan.modules.BinaryLuan;
-import luan.modules.JavaLuan;
 
 
 final class IndexExpr extends BinaryOpExpr {
@@ -18,21 +12,7 @@
 	}
 
 	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		return index(luan,op1.eval(luan),op2.eval(luan));
+		return LuanTable.index( luan.bit(op1.el()), op1.eval(luan), op2.eval(luan) );
 	}
 
-	private Object index(LuanStateImpl luan,Object obj,Object key) throws LuanException {
-		if( obj instanceof LuanTable ) {
-			LuanTable tbl = (LuanTable)obj;
-			return tbl.get(luan,key);
-		}
-		if( obj instanceof String )
-			return StringLuan.__index(luan,(String)obj,key);
-		if( obj instanceof byte[] )
-			return BinaryLuan.__index(luan,(byte[])obj,key);
-		if( obj != null && luan.currentEnvironment().hasJava() )
-			return JavaLuan.__index(luan,obj,key);
-		else
-			throw luan.bit(op1.el()).exception( "attempt to index '"+op1.el().text()+"' (a " + Luan.type(obj) + " value)" );
-	}
 }
diff -r f26485a3692c -r d3183a330ff5 core/src/luan/modules/BasicLuan.java
--- a/core/src/luan/modules/BasicLuan.java	Mon May 18 23:23:01 2015 -0600
+++ b/core/src/luan/modules/BasicLuan.java	Tue May 19 17:57:20 2015 -0600
@@ -64,7 +64,8 @@
 		};
 	}
 
-	public static Object get_metatable(LuanTable table) {
+	public static Object get_metatable(LuanState luan,LuanTable table) throws LuanException {
+		Utils.checkNotNull(luan,table);
 		LuanTable metatable = table.getMetatable();
 		if( metatable == null )
 			return null;
@@ -73,6 +74,7 @@
 	}
 
 	public static void set_metatable(LuanState luan,LuanTable table,LuanTable metatable) throws LuanException {
+		Utils.checkNotNull(luan,table);
 		if( table.getHandler("__metatable") != null )
 			throw luan.exception("cannot change a protected metatable");
 		table.setMetatable(metatable);
diff -r f26485a3692c -r d3183a330ff5 core/src/luan/modules/JavaLuan.java
--- a/core/src/luan/modules/JavaLuan.java	Mon May 18 23:23:01 2015 -0600
+++ b/core/src/luan/modules/JavaLuan.java	Tue May 19 17:57:20 2015 -0600
@@ -307,7 +307,7 @@
 			return cls.isSynthetic();
 		}
 
-		public Object luan_proxy(final LuanState luan,final LuanTable t,final Object base) throws LuanException {
+		public Object luan_proxy(final LuanState luan,final LuanTable t) throws LuanException {
 			return Proxy.newProxyInstance(
 				cls.getClassLoader(),
 				new Class[]{cls},
@@ -319,8 +319,8 @@
 							args = new Object[0];
 						String name = method.getName();
 						Object fnObj = t.get(luan,name);
-						if( fnObj==null && base!=null )
-							return method.invoke(base,args);
+						if( fnObj == null )
+							throw new NullPointerException("luan_proxy couldn't find method '"+name+"'");
 						LuanFunction fn = luan.checkFunction(fnObj);
 						return Luan.first(luan.call(fn,name,args));
 					}
@@ -331,7 +331,7 @@
 	private static final Method luan_proxyMethod;
 	static {
 		try {
-			luan_proxyMethod = Static.class.getMethod("luan_proxy",LuanState.class,LuanTable.class,Object.class);
+			luan_proxyMethod = Static.class.getMethod("luan_proxy",LuanState.class,LuanTable.class);
 			luan_proxyMethod.setAccessible(true);
 		} catch(NoSuchMethodException e) {
 			throw new RuntimeException(e);
diff -r f26485a3692c -r d3183a330ff5 website/src/manual.html.luan
--- a/website/src/manual.html.luan	Mon May 18 23:23:01 2015 -0600
+++ b/website/src/manual.html.luan	Tue May 19 17:57:20 2015 -0600
@@ -343,7 +343,7 @@
 
 <ul>
 
-<li><b>"add": </b>
+<li><p><b>"add": </b>
 the <tt>+</tt> operation.
 
 If any operand for an addition is a table,
@@ -360,49 +360,49 @@
 it raises an error.
 </li>
 
-<li><b>"sub": </b>
+<li><p><b>"sub": </b>
 the <tt>-</tt> operation.
 
 Behavior similar to the "add" operation.
 </li>
 
-<li><b>"mul": </b>
+<li><p><b>"mul": </b>
 the <tt>*</tt> operation.
 
 Behavior similar to the "add" operation.
 </li>
 
-<li><b>"div": </b>
+<li><p><b>"div": </b>
 the <tt>/</tt> operation.
 
 Behavior similar to the "add" operation.
 </li>
 
-<li><b>"mod": </b>
+<li><p><b>"mod": </b>
 the <tt>%</tt> operation.
 
 Behavior similar to the "add" operation.
 </li>
 
-<li><b>"pow": </b>
+<li><p><b>"pow": </b>
 the <tt>^</tt> (exponentiation) operation.
 
 Behavior similar to the "add" operation.
 </li>
 
-<li><b>"unm": </b>
+<li><p><b>"unm": </b>
 the <tt>-</tt> (unary minus) operation.
 
 Behavior similar to the "add" operation.
 </li>
 
-<li><b>"concat": </b>
+<li><p><b>"concat": </b>
 the <tt>..</tt> (concatenation) operation.
 
 Behavior similar to the "add" operation.
 </li>
 
-<li><b>"len": </b>
+<li><p><b>"len": </b>
 the <tt>#</tt> (length) operation.
 
 If there is a metamethod,
@@ -415,7 +415,7 @@
 Otherwise, Luan raises an error.
 </li>
 
-<li><b>"eq": </b>
+<li><p><b>"eq": </b>
 the <tt>==</tt> (equal) operation.
 
 Behavior similar to the "add" operation,
@@ -425,14 +425,14 @@
 The result of the call is always converted to a boolean.
 </li>
 
-<li><b>"lt": </b>
+<li><p><b>"lt": </b>
 the <tt>&lt;</tt> (less than) operation.
 
 Behavior similar to the "add" operation.
 The result of the call is always converted to a boolean.
 </li>
 
-<li><b>"le": </b>
+<li><p><b>"le": </b>
 the <tt>&lt;=</tt> (less equal) operation.
 
 Unlike other operations,
@@ -446,7 +446,7 @@
 the result is always a boolean.
 </li>
 
-<li><b>"index": </b>
+<li><p><b>"index": </b>
 The indexing access <tt>table[key]</tt>.
 
 This event happens
@@ -456,16 +456,16 @@
 
 <p>
 Despite the name,
-the metamethod for this event can be either a function or a table.
+the metamethod for this event can be any type.
 If it is a function,
 it is called with <tt>table</tt> and <tt>key</tt> as arguments.
-If it is a table,
-the final result is the result of indexing this table with <tt>key</tt>.
+Otherwise
+the final result is the result of indexing this metamethod object with <tt>key</tt>.
 (This indexing is regular, not raw,
-and therefore can trigger another metamethod.)
+and therefore can trigger another metamethod if the metamethod object is a table.)
 </li>
 
-<li><b>"new_index": </b>
+<li><p><b>"new_index": </b>
 The indexing assignment <tt>table[key] = value</tt>.
 
 Like the index event,
@@ -493,7 +493,7 @@
 to do the assignment.)
 </li>
 
-<li><b>"call": </b>
+<li><p><b>"call": </b>
 The call operation <tt>func(args)</tt>.
 
 This event happens when Luan tries to call a table.