changeset 419:8fbb961aabd5

improve repr() to check metamethod recursively
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 30 Apr 2015 23:15:40 -0600
parents 455784e2227d
children e9d4d5854e54
files core/src/luan/Luan.java core/src/luan/LuanBit.java core/src/luan/LuanFunction.java core/src/luan/LuanRepr.java core/src/luan/LuanState.java core/src/luan/LuanTable.java core/src/luan/impl/FnCall.java core/src/luan/impl/IndexExpr.java core/src/luan/impl/SetTableEntry.java core/src/luan/modules/BasicLuan.java
diffstat 10 files changed, 40 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/core/src/luan/Luan.java	Thu Apr 30 21:52:20 2015 -0600
+++ b/core/src/luan/Luan.java	Thu Apr 30 23:15:40 2015 -0600
@@ -135,19 +135,5 @@
 		return s;
 	}
 
-	public static String repr(Object obj) {
-		if( obj == null )
-			return "nil";
-		if( obj instanceof Boolean )
-			return Luan.toString((Boolean)obj);
-		if( obj instanceof Number )
-			return Luan.toString((Number)obj);
-		if( obj instanceof String )
-			return "\"" + stringEncode((String)obj) + "\"";
-		if( obj instanceof LuanRepr )
-			return ((LuanRepr)obj).repr();
-		return null;
-	}
-
 	private Luan() {}  // never
 }
--- a/core/src/luan/LuanBit.java	Thu Apr 30 21:52:20 2015 -0600
+++ b/core/src/luan/LuanBit.java	Thu Apr 30 23:15:40 2015 -0600
@@ -90,7 +90,7 @@
 	public String toString(Object obj) throws LuanException {
 		if( obj instanceof LuanTable ) {
 			LuanTable tbl = (LuanTable)obj;
-			Object h = luan.getHandler("__tostring",tbl);
+			Object h = tbl.getHandler("__tostring");
 			if( h instanceof LuanMeta ) {
 				LuanMeta meta = (LuanMeta)h;
 				return meta.__tostring(luan,tbl);
@@ -103,19 +103,21 @@
 	}
 
 	public String repr(Object obj) throws LuanException {
-		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;
+		if( obj == null )
+			return "nil";
+		if( obj instanceof Boolean )
+			return Luan.toString((Boolean)obj);
+		if( obj instanceof Number )
+			return Luan.toString((Number)obj);
+		if( obj instanceof String )
+			return "\"" + Luan.stringEncode((String)obj) + "\"";
+		if( obj instanceof LuanRepr )
+			return ((LuanRepr)obj).repr(luan);
+		throw exception( "value '" + obj + "' doesn't support repr()" );
 	}
 
 	public LuanFunction getHandlerFunction(String op,LuanTable t) throws LuanException {
-		Object f = luan.getHandler(op,t);
+		Object f = t.getHandler(op);
 		if( f == null )
 			return null;
 		return checkFunction(f);
--- a/core/src/luan/LuanFunction.java	Thu Apr 30 21:52:20 2015 -0600
+++ b/core/src/luan/LuanFunction.java	Thu Apr 30 23:15:40 2015 -0600
@@ -8,10 +8,10 @@
 	public static final Object[] NOTHING = new Object[0];
 
 	@Override public String toString() {
-		return "function: " + Integer.toHexString(hashCode());
+		return "function:" + Integer.toHexString(hashCode());
 	}
 
-	@Override public String repr() {
+	@Override public String repr(LuanState luan) {
 		return "<" + toString() + ">";
 	}
 
--- a/core/src/luan/LuanRepr.java	Thu Apr 30 21:52:20 2015 -0600
+++ b/core/src/luan/LuanRepr.java	Thu Apr 30 23:15:40 2015 -0600
@@ -2,5 +2,5 @@
 
 
 public interface LuanRepr {
-	public String repr();
+	public String repr(LuanState luan) throws LuanException;
 }
--- a/core/src/luan/LuanState.java	Thu Apr 30 21:52:20 2015 -0600
+++ b/core/src/luan/LuanState.java	Thu Apr 30 23:15:40 2015 -0600
@@ -46,14 +46,9 @@
 		return new LuanBit(this,el);
 	}
 
-	public final static Object getHandler(String op,LuanTable table) {
-		LuanTable t = table.getMetatable();
-		return t==null ? null : t.get(op);
-	}
-
 	// convenience methods
 
-	private final LuanBit JAVA = bit(LuanElement.JAVA);
+	final LuanBit JAVA = bit(LuanElement.JAVA);
 
 	public LuanException exception(Object msg) {
 		return JAVA.exception(msg);
--- a/core/src/luan/LuanTable.java	Thu Apr 30 21:52:20 2015 -0600
+++ b/core/src/luan/LuanTable.java	Thu Apr 30 23:15:40 2015 -0600
@@ -281,6 +281,11 @@
 		this.metatable = metatable;
 	}
 
+	public Object getHandler(String op) {
+		LuanTable t = getMetatable();
+		return t==null ? null : t.get(op);
+	}
+
 	public boolean hasJava() {
 		return hasJava;
 	}
@@ -328,11 +333,14 @@
 		return isList() ? new LuanTable(new ArrayList<Object>(asList())) : new LuanTable(asMap());
 	}
 
-	@Override public String repr() {
-		return repr( Collections.newSetFromMap(new IdentityHashMap<LuanTable,Boolean>()) );
+	@Override public String repr(LuanState luan) throws LuanException {
+		LuanFunction fn = luan.JAVA.getHandlerFunction("__repr",this);
+		if( fn != null )
+			return luan.JAVA.checkString( Luan.first( luan.call(fn,"__repr",new Object[]{this}) ) );
+		return repr( luan, Collections.newSetFromMap(new IdentityHashMap<LuanTable,Boolean>()) );
 	}
 
-	private String repr(Set<LuanTable> set) {
+	private String repr(LuanState luan,Set<LuanTable> set) throws LuanException {
 		if( !set.add(this) ) {
 			return "\"<circular reference>\"";
 		}
@@ -345,7 +353,7 @@
 			} else {
 				sb.append(", ");
 			}
-			sb.append(repr(set,obj));
+			sb.append(repr(luan,set,obj));
 		}
 		for( Map.Entry<Object,Object> entry : map().entrySet() ) {
 			if( isFirst ) {
@@ -353,7 +361,7 @@
 			} else {
 				sb.append(", ");
 			}
-			sb.append(reprKey(set,entry.getKey())).append('=').append(repr(set,entry.getValue()));
+			sb.append(reprKey(luan,set,entry.getKey())).append('=').append(repr(luan,set,entry.getValue()));
 		}
 		sb.append('}');
 		return sb.toString();
@@ -361,21 +369,21 @@
 
 	private static final Pattern namePtn = Pattern.compile("[a-zA-Z_][a-zA-Z_0-9]*");
 
-	private String reprKey(Set<LuanTable> set,Object obj) {
+	private String reprKey(LuanState luan,Set<LuanTable> set,Object obj) throws LuanException {
 		if( obj instanceof String ) {
 			String s = (String)obj;
 			if( namePtn.matcher(s).matches() )
 				return s;
 		}
-		return "[" + repr(set,obj) + "]";
+		return "[" + repr(luan,set,obj) + "]";
 	}
 
-	private String repr(Set<LuanTable> set,Object obj) {
+	private String repr(LuanState luan,Set<LuanTable> set,Object obj) throws LuanException {
 		if( obj instanceof LuanTable ) {
 			LuanTable t = (LuanTable)obj;
-			return t.repr(set);
+			return t.repr(luan,set);
 		} else {
-			String s = Luan.repr(obj);
+			String s = luan.repr(obj);
 			if( s == null )
 				s = "<couldn't repr: " + Luan.stringEncode(Luan.toString(obj)) + ">";
 			return s;
--- a/core/src/luan/impl/FnCall.java	Thu Apr 30 21:52:20 2015 -0600
+++ b/core/src/luan/impl/FnCall.java	Thu Apr 30 23:15:40 2015 -0600
@@ -29,7 +29,8 @@
 			return luan.bit(se).call( fn, fnName, Luan.array(args.eval(luan)) );
 		}
 		if( o instanceof LuanTable ) {
-			Object h = luan.getHandler("__call",(LuanTable)o);
+			LuanTable t = (LuanTable)o;
+			Object h = t.getHandler("__call");
 			if( h != null )
 				return call(luan,h);
 		}
--- a/core/src/luan/impl/IndexExpr.java	Thu Apr 30 21:52:20 2015 -0600
+++ b/core/src/luan/impl/IndexExpr.java	Thu Apr 30 23:15:40 2015 -0600
@@ -27,7 +27,7 @@
 			Object value = tbl.get(key);
 			if( value != null )
 				return value;
-			Object h = luan.getHandler("__index",tbl);
+			Object h = tbl.getHandler("__index");
 			if( h==null )
 				return null;
 			if( h instanceof LuanFunction ) {
--- a/core/src/luan/impl/SetTableEntry.java	Thu Apr 30 21:52:20 2015 -0600
+++ b/core/src/luan/impl/SetTableEntry.java	Thu Apr 30 23:15:40 2015 -0600
@@ -26,7 +26,7 @@
 	private void newindex(LuanStateImpl luan,Object t,Object key,Object value) throws LuanException {
 		if( t instanceof LuanTable ) {
 			LuanTable table = (LuanTable)t;
-			Object h = luan.getHandler("__newindex",table);
+			Object h = table.getHandler("__newindex");
 			if( h==null || table.get(key)!=null ) {
 				try {
 					table.put(key,value);
--- a/core/src/luan/modules/BasicLuan.java	Thu Apr 30 21:52:20 2015 -0600
+++ b/core/src/luan/modules/BasicLuan.java	Thu Apr 30 23:15:40 2015 -0600
@@ -50,7 +50,7 @@
 
 	public static LuanFunction pairs(LuanState luan,final LuanTable t) throws LuanException {
 		Utils.checkNotNull(luan,t);
-		Object obj = luan.getHandler("__pairs",t);
+		Object obj = t.getHandler("__pairs");
 		if( obj != null ) {
 			if( obj instanceof LuanFunction ) {
 				obj = Luan.first(luan.call((LuanFunction)obj,"__pairs",new Object[]{t}));