diff core/src/luan/AbstractLuanTable.java @ 355:1bce334a816b

AbstractLuanTable now implements LuanRepr
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 14 Apr 2015 09:33:34 -0600
parents 9fb523472035
children 1a464e090538
line wrap: on
line diff
--- a/core/src/luan/AbstractLuanTable.java	Tue Apr 14 05:44:06 2015 -0600
+++ b/core/src/luan/AbstractLuanTable.java	Tue Apr 14 09:33:34 2015 -0600
@@ -14,7 +14,7 @@
 import java.util.regex.Pattern;
 
 
-public abstract class AbstractLuanTable implements LuanTable {
+public abstract class AbstractLuanTable implements LuanTable, LuanRepr {
 
 	protected final Map<Object,Object> newMap() {
 		return new LinkedHashMap<Object,Object>();
@@ -44,6 +44,11 @@
 		return map;
 	}
 
+	// shouldn't include list
+	protected Map<Object,Object> map() {
+		return asMap();
+	}
+
 	protected abstract String type();
 
 	@Override public final String toString() {
@@ -96,4 +101,59 @@
 	@Override public void setJava() {
 		throw new UnsupportedOperationException();
 	}
+
+	@Override public String repr() {
+		return repr( Collections.newSetFromMap(new IdentityHashMap<AbstractLuanTable,Boolean>()) );
+	}
+
+	private String repr(Set<AbstractLuanTable> set) {
+		if( !set.add(this) ) {
+			return "\"<circular reference>\"";
+		}
+		StringBuilder sb = new StringBuilder();
+		sb.append('{');
+		boolean isFirst = true;
+		for( Object obj : asList() ) {
+			if( isFirst ) {
+				isFirst = false;
+			} else {
+				sb.append(", ");
+			}
+			sb.append(repr(set,obj));
+		}
+		for( Map.Entry<Object,Object> entry : map().entrySet() ) {
+			if( isFirst ) {
+				isFirst = false;
+			} else {
+				sb.append(", ");
+			}
+			sb.append(reprKey(set,entry.getKey())).append('=').append(repr(set,entry.getValue()));
+		}
+		sb.append('}');
+		return sb.toString();
+	}
+
+	private static final Pattern namePtn = Pattern.compile("[a-zA-Z_][a-zA-Z_0-9]*");
+
+	private String reprKey(Set<AbstractLuanTable> set,Object obj) {
+		if( obj instanceof String ) {
+			String s = (String)obj;
+			if( namePtn.matcher(s).matches() )
+				return s;
+		}
+		return "[" + repr(set,obj) + "]";
+	}
+
+	String repr(Set<AbstractLuanTable> set,Object obj) {
+		if( obj instanceof AbstractLuanTable ) {
+			AbstractLuanTable t = (AbstractLuanTable)obj;
+			return t.repr(set);
+		} else {
+			String s = Luan.repr(obj);
+			if( s == null )
+				s = "<couldn't repr: " + Luan.stringEncode(Luan.toString(obj)) + ">";
+			return s;
+		}
+	}
+
 }