diff core/src/luan/modules/StringLuan.java @ 195:24ede40ee0aa

make MetatableGetter DeepCloneable, scoped, and secure git-svn-id: https://luan-java.googlecode.com/svn/trunk@196 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Thu, 03 Jul 2014 08:19:48 +0000
parents 3dcb0f9bee82
children be0275bda373
line wrap: on
line diff
--- a/core/src/luan/modules/StringLuan.java	Wed Jul 02 04:52:25 2014 +0000
+++ b/core/src/luan/modules/StringLuan.java	Thu Jul 03 08:19:48 2014 +0000
@@ -10,14 +10,15 @@
 import luan.LuanElement;
 import luan.LuanException;
 import luan.MetatableGetter;
+import luan.DeepCloner;
 
 
 public final class StringLuan {
 
 	public static final LuanFunction LOADER = new LuanFunction() {
 		@Override public Object call(LuanState luan,Object[] args) {
-			luan.addMetatableGetter(mg);
 			LuanTable module = new LuanTable();
+			module.metatableGetter = new MyMetatableGetter(module);
 			try {
 				add( module, "to_binary", String.class );
 				add( module, "to_integers", String.class );
@@ -44,25 +45,23 @@
 		t.put( method, new LuanJavaFunction(StringLuan.class.getMethod(method,parameterTypes),null) );
 	}
 
-	private static final LuanTable mt = new LuanTable();
-	static {
-		try {
-			add( mt, "__index", LuanState.class, String.class, Object.class );
-		} catch(NoSuchMethodException e) {
-			throw new RuntimeException(e);
-		}
-	}
+	public static class MyMetatableGetter implements MetatableGetter {
+		private LuanTable module;
+		private LuanTable metatable;
+
+		private MyMetatableGetter() {}
 
-	private static final MetatableGetter mg = new MetatableGetter() {
-		public LuanTable getMetatable(Object obj) {
-			return obj instanceof String ? mt : null;
+		MyMetatableGetter(LuanTable module) {
+			this.module = module;
+			this.metatable = table();
 		}
-	};
 
-	public static Object __index(LuanState luan,final String s,Object key) throws LuanException {
-		LuanTable mod = (LuanTable)luan.loaded().get("String");
-		if( mod!=null ) {
-			Object obj = mod.get(key);
+		@Override public LuanTable getMetatable(Object obj) {
+			return obj instanceof String ? metatable : null;
+		}
+
+		public Object __index(LuanState luan,final String s,Object key) throws LuanException {
+			Object obj = module.get(key);
 			if( obj instanceof LuanFunction ) {
 				final LuanFunction fn = (LuanFunction)obj;
 				return new LuanFunction() {
@@ -74,10 +73,37 @@
 					}
 				};
 			}
+			LuanTable mt = luan.getMetatable(s,this);
+			if( mt == null )
+				return null;
+			Object h = mt.get("__index");
+			if( !(h instanceof LuanFunction) )
+				return null;
+			LuanFunction fn = (LuanFunction)h;
+			return luan.call(fn,new Object[]{s,key});
 		}
-		if( luan.loaded().get("Java") != null )
-			return JavaLuan.__index(luan,s,key);
-		return null;
+
+		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) {