changeset 197:4c96cb73dd93

fix metatable cloning git-svn-id: https://luan-java.googlecode.com/svn/trunk@198 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Thu, 03 Jul 2014 18:36:46 +0000
parents be0275bda373
children 390210409719
files core/src/luan/LuanJavaFunction.java core/src/luan/modules/JavaLuan.java core/src/luan/modules/StringLuan.java
diffstat 3 files changed, 126 insertions(+), 99 deletions(-) [+]
line wrap: on
line diff
--- a/core/src/luan/LuanJavaFunction.java	Thu Jul 03 18:03:53 2014 +0000
+++ b/core/src/luan/LuanJavaFunction.java	Thu Jul 03 18:36:46 2014 +0000
@@ -11,9 +11,9 @@
 import java.util.Arrays;
 
 
-public final class LuanJavaFunction extends LuanFunction {
+public final class LuanJavaFunction extends LuanFunction implements DeepCloneable<LuanJavaFunction> {
 	private final JavaMethod method;
-	private final Object obj;
+	private Object obj;
 	private final RtnConverter rtnConverter;
 	private final boolean takesLuaState;
 	private final ArgConverter[] argConverters;
@@ -41,6 +41,22 @@
 		}
 	}
 
+	private LuanJavaFunction(LuanJavaFunction f) {
+		this.method = f.method;
+		this.rtnConverter = f.rtnConverter;
+		this.takesLuaState = f.takesLuaState;
+		this.argConverters = f.argConverters;
+		this.varArgCls = f.varArgCls;
+	}
+
+	@Override public LuanJavaFunction shallowClone() {
+		return obj==null ? this : new LuanJavaFunction(this);
+	}
+
+	@Override public void deepenClone(LuanJavaFunction clone,DeepCloner cloner) {
+		clone.obj = cloner.get(obj);
+	}
+
 	@Override public String toString() {
 		return "java-function: " + method;
 	}
--- a/core/src/luan/modules/JavaLuan.java	Thu Jul 03 18:03:53 2014 +0000
+++ b/core/src/luan/modules/JavaLuan.java	Thu Jul 03 18:36:46 2014 +0000
@@ -32,7 +32,9 @@
 	public static final LuanFunction LOADER = new LuanFunction() {
 		@Override public Object call(LuanState luan,Object[] args) {
 			LuanTable module = new LuanTable();
-			module.put( MetatableGetter.KEY, mg );
+			MyMetatableGetter mmg = new MyMetatableGetter();
+			mmg.init();
+			module.put( MetatableGetter.KEY, mmg );
 			try {
 				module.put( "class", new LuanJavaFunction(JavaLuan.class.getMethod("getClass",LuanState.class,String.class),null) );
 				add( module, "proxy", LuanState.class, Static.class, LuanTable.class, Object.class );
@@ -67,92 +69,104 @@
 		}
 	}
 
-	private static final LuanTable mt = new LuanTable();
-	static {
-		add( mt, "__index", LuanState.class, Object.class, Object.class );
-		add( mt, "__newindex", LuanState.class, Object.class, Object.class, Object.class );
-	}
+	public static class MyMetatableGetter implements MetatableGetter {
+		private LuanTable metatable;
+
+		private MyMetatableGetter() {}
 
-	private static final MetatableGetter mg = new MetatableGetter() {
-
-		public LuanTable getMetatable(Object obj) {
-			if( obj==null )
-				return null;
-			return mt;
+		private void init() {
+			this.metatable = new LuanTable();
+			try {
+				metatable.put( "__index", new LuanJavaFunction(
+					MyMetatableGetter.class.getMethod( "__index", LuanState.class, Object.class, Object.class ), this
+				) );
+			} catch(NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			}
+			add( metatable, "__newindex", LuanState.class, Object.class, Object.class, Object.class );
 		}
 
 		@Override public MetatableGetter shallowClone() {
-			return this;
+			return new MyMetatableGetter();
+		}
+
+		@Override public void deepenClone(MetatableGetter c,DeepCloner cloner) {
+			MyMetatableGetter clone = (MyMetatableGetter)c;
+			clone.metatable = cloner.deepClone(metatable);
 		}
-		@Override public void deepenClone(MetatableGetter clone,DeepCloner cloner) {}
-	};
+
+		@Override public LuanTable getMetatable(Object obj) {
+			if( obj==null )
+				return null;
+			return metatable;
+		}
 
-	public static Object __index(LuanState luan,Object obj,Object key) throws LuanException {
-		LuanTable mt = luan.getMetatable(obj,mg);
-		if( mt != null ) {
-			Object h = mt.get("__index");
-			if( h instanceof LuanFunction ) {
-				LuanFunction fn = (LuanFunction)h;
-				Object rtn = Luan.first(luan.call(fn,new Object[]{obj,key}));
-				if( rtn != null )
-					return rtn;
+		public Object __index(LuanState luan,Object obj,Object key) throws LuanException {
+			LuanTable mt = luan.getMetatable(obj,this);
+			if( mt != null ) {
+				Object h = mt.get("__index");
+				if( h instanceof LuanFunction ) {
+					LuanFunction fn = (LuanFunction)h;
+					Object rtn = Luan.first(luan.call(fn,new Object[]{obj,key}));
+					if( rtn != null )
+						return rtn;
+				}
 			}
-		}
-		if( obj instanceof Static ) {
+			if( obj instanceof Static ) {
+				if( key instanceof String ) {
+					String name = (String)key;
+					Static st = (Static)obj;
+					Class cls = st.cls;
+					if( "class".equals(name) ) {
+						return cls;
+					} else if( "new".equals(name) ) {
+						Constructor<?>[] constructors = cls.getConstructors();
+						if( constructors.length > 0 ) {
+							if( constructors.length==1 ) {
+								return new LuanJavaFunction(constructors[0],null);
+							} else {
+								List<LuanJavaFunction> fns = new ArrayList<LuanJavaFunction>();
+								for( Constructor constructor : constructors ) {
+									fns.add(new LuanJavaFunction(constructor,null));
+								}
+								return new AmbiguousJavaFunction(fns);
+							}
+						}
+					} else if( "assert".equals(name) ) {
+						return new LuanJavaFunction(assertClass,new AssertClass(cls));
+					} else {
+						List<Member> members = getStaticMembers(cls,name);
+						if( !members.isEmpty() ) {
+							return member(null,members);
+						}
+					}
+				}
+				throw luan.exception("invalid member '"+key+"' for: "+obj);
+			}
+			Class cls = obj.getClass();
+			if( cls.isArray() ) {
+				if( "length".equals(key) ) {
+					return Array.getLength(obj);
+				}
+				Integer i = Luan.asInteger(key);
+				if( i != null ) {
+					return Array.get(obj,i);
+				}
+				throw luan.exception("invalid member '"+key+"' for java array: "+obj);
+			}
 			if( key instanceof String ) {
 				String name = (String)key;
-				Static st = (Static)obj;
-				Class cls = st.cls;
-				if( "class".equals(name) ) {
-					return cls;
-				} else if( "new".equals(name) ) {
-					Constructor<?>[] constructors = cls.getConstructors();
-					if( constructors.length > 0 ) {
-						if( constructors.length==1 ) {
-							return new LuanJavaFunction(constructors[0],null);
-						} else {
-							List<LuanJavaFunction> fns = new ArrayList<LuanJavaFunction>();
-							for( Constructor constructor : constructors ) {
-								fns.add(new LuanJavaFunction(constructor,null));
-							}
-							return new AmbiguousJavaFunction(fns);
-						}
-					}
-				} else if( "assert".equals(name) ) {
-					return new LuanJavaFunction(assertClass,new AssertClass(cls));
+				if( "instanceof".equals(name) ) {
+					return new LuanJavaFunction(instanceOf,new InstanceOf(obj));
 				} else {
-					List<Member> members = getStaticMembers(cls,name);
+					List<Member> members = getMembers(cls,name);
 					if( !members.isEmpty() ) {
-						return member(null,members);
+						return member(obj,members);
 					}
 				}
 			}
-			throw luan.exception("invalid member '"+key+"' for: "+obj);
-		}
-		Class cls = obj.getClass();
-		if( cls.isArray() ) {
-			if( "length".equals(key) ) {
-				return Array.getLength(obj);
-			}
-			Integer i = Luan.asInteger(key);
-			if( i != null ) {
-				return Array.get(obj,i);
-			}
-			throw luan.exception("invalid member '"+key+"' for java array: "+obj);
+			return null;
 		}
-		if( key instanceof String ) {
-			String name = (String)key;
-			if( "instanceof".equals(name) ) {
-				return new LuanJavaFunction(instanceOf,new InstanceOf(obj));
-			} else {
-				List<Member> members = getMembers(cls,name);
-				if( !members.isEmpty() ) {
-					return member(obj,members);
-				}
-			}
-		}
-//		throw luan.exception("invalid member '"+key+"' for java object: "+obj);
-		return null;
 	}
 
 	private static Object member(Object obj,List<Member> members) throws LuanException {
--- a/core/src/luan/modules/StringLuan.java	Thu Jul 03 18:03:53 2014 +0000
+++ b/core/src/luan/modules/StringLuan.java	Thu Jul 03 18:36:46 2014 +0000
@@ -18,7 +18,9 @@
 	public static final LuanFunction LOADER = new LuanFunction() {
 		@Override public Object call(LuanState luan,Object[] args) {
 			LuanTable module = new LuanTable();
-			module.put( MetatableGetter.KEY, new MyMetatableGetter(module) );
+			MyMetatableGetter mmg = new MyMetatableGetter();
+			mmg.init(module);
+			module.put( MetatableGetter.KEY, mmg );
 			try {
 				add( module, "to_binary", String.class );
 				add( module, "to_integers", String.class );
@@ -51,9 +53,26 @@
 
 		private MyMetatableGetter() {}
 
-		MyMetatableGetter(LuanTable module) {
+		private void init(LuanTable module) {
 			this.module = module;
-			this.metatable = table();
+			this.metatable = new LuanTable();
+			try {
+				metatable.put( "__index", new LuanJavaFunction(
+					MyMetatableGetter.class.getMethod( "__index", LuanState.class, String.class, Object.class ), this
+				) );
+			} catch(NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			}
+		}
+
+		@Override public MetatableGetter shallowClone() {
+			return new MyMetatableGetter();
+		}
+
+		@Override public void deepenClone(MetatableGetter c,DeepCloner cloner) {
+			MyMetatableGetter clone = (MyMetatableGetter)c;
+			clone.module = cloner.deepClone(module);
+			clone.metatable = cloner.deepClone(metatable);
 		}
 
 		@Override public LuanTable getMetatable(Object obj) {
@@ -82,28 +101,6 @@
 			LuanFunction fn = (LuanFunction)h;
 			return luan.call(fn,new Object[]{s,key});
 		}
-
-		LuanTable table() {
-			LuanTable tbl = new LuanTable();
-			try {
-				tbl.put( "__index", new LuanJavaFunction(
-					MyMetatableGetter.class.getMethod( "__index", LuanState.class, String.class, Object.class ), this
-				) );
-			} catch(NoSuchMethodException e) {
-				throw new RuntimeException(e);
-			}
-			return tbl;
-		}
-
-		@Override public MetatableGetter shallowClone() {
-			return new MyMetatableGetter();
-		}
-
-		@Override public void deepenClone(MetatableGetter c,DeepCloner cloner) {
-			MyMetatableGetter clone = (MyMetatableGetter)c;
-			clone.module = cloner.deepClone(module);
-			clone.metatable = clone.table();
-		}
 	}
 
 	static int start(String s,int i) {