changeset 208:5ba136769034

remove MetatableGetter and use a generic metatable instead git-svn-id: https://luan-java.googlecode.com/svn/trunk@209 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Tue, 08 Jul 2014 07:04:47 +0000
parents 5aafb5b9f70f
children 239c8d650028
files core/src/luan/LuanState.java core/src/luan/MetatableGetter.java core/src/luan/impl/Closure.java core/src/luan/impl/FnDef.java core/src/luan/impl/LuanCompiler.java core/src/luan/impl/LuanStateImpl.java core/src/luan/impl/MtGetterLink.java core/src/luan/modules/JavaLuan.java core/src/luan/modules/PackageLuan.java core/src/luan/modules/StringLuan.java dist/luan-core-trunk.jar dist/luan-logging-trunk.jar dist/luan-web-trunk.jar web/src/luan/modules/web/web_run.luan
diffstat 14 files changed, 107 insertions(+), 255 deletions(-) [+]
line wrap: on
line diff
--- a/core/src/luan/LuanState.java	Tue Jul 08 02:04:24 2014 +0000
+++ b/core/src/luan/LuanState.java	Tue Jul 08 07:04:47 2014 +0000
@@ -11,6 +11,8 @@
 import luan.impl.LuanCompiler;
 import luan.modules.BasicLuan;
 import luan.modules.PackageLuan;
+import luan.modules.JavaLuan;
+import luan.modules.StringLuan;
 
 
 public abstract class LuanState implements DeepCloneable<LuanState> {
@@ -19,11 +21,13 @@
 
 	private LuanTable registry;
 	private LuanTable global;
+	private LuanTable metatable;  // generic metatable
 
 	protected LuanState() {
 		registry = new LuanTable();
 		global = new LuanTable();
 		global.put("_G",global);
+		metatable = newMetatable();
 	}
 
 	protected LuanState(LuanState luan) {}
@@ -31,6 +35,7 @@
 	@Override public void deepenClone(LuanState clone,DeepCloner cloner) {
 		clone.registry = cloner.deepClone(registry);
 		clone.global = cloner.deepClone(global);
+		clone.metatable = cloner.deepClone(metatable);
 	}
 
 	public abstract LuanTable currentEnvironment();
@@ -76,13 +81,15 @@
 	}
 
 	public final LuanTable getMetatable(Object obj) {
-		return getMetatable(obj,null);
+		if( obj==null )
+			return null;
+		if( obj instanceof LuanTable ) {
+			LuanTable table = (LuanTable)obj;
+			return table.getMetatable();
+		}
+		return metatable;
 	}
 
-	public abstract LuanTable getMetatable(Object obj,MetatableGetter beforeThis);
-
-	public abstract void addMetatableGetter(MetatableGetter mg);
-
 	public final LuanBit bit(LuanElement el) {
 		return new LuanBit(this,el);
 	}
@@ -92,6 +99,33 @@
 		return t==null ? null : t.get(op);
 	}
 
+	private static LuanTable newMetatable() {
+		LuanTable metatable = new LuanTable();
+		try {
+			metatable.put( "__index", new LuanJavaFunction(
+				LuanState.class.getMethod("__index",LuanState.class,Object.class,Object.class), null
+			) );
+			metatable.put( "__newindex", new LuanJavaFunction(
+				LuanState.class.getMethod("__newindex",LuanState.class,Object.class,Object.class,Object.class), null
+			) );
+		} catch(NoSuchMethodException e) {
+			throw new RuntimeException(e);
+		}
+		return metatable;
+	}
+
+	public static Object __index(LuanState luan,Object obj,Object key) throws LuanException {
+		if( obj instanceof String ) {
+			Object rtn = StringLuan.__index(luan,(String)obj,key);
+			if( rtn != null )
+				return rtn;
+		}
+		return JavaLuan.__index(luan,obj,key);
+	}
+
+	public static void __newindex(LuanState luan,Object obj,Object key,Object value) throws LuanException {
+		JavaLuan.__newindex(luan,obj,key,value);
+	}
 
 	// convenience methods
 
--- a/core/src/luan/MetatableGetter.java	Tue Jul 08 02:04:24 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-package luan;
-
-public interface MetatableGetter extends DeepCloneable<MetatableGetter> {
-	public static final String KEY = "_METATABLE_GETTER";
-	public LuanTable getMetatable(Object obj);
-}
--- a/core/src/luan/impl/Closure.java	Tue Jul 08 02:04:24 2014 +0000
+++ b/core/src/luan/impl/Closure.java	Tue Jul 08 07:04:47 2014 +0000
@@ -11,12 +11,10 @@
 
 final class Closure extends LuanFunction implements DeepCloneable<Closure> {
 	private final FnDef fnDef;
-	private MtGetterLink mtGetterLink;
 	private UpValue[] upValues;
 
-	Closure(LuanStateImpl luan,FnDef fnDef,MtGetterLink mtGetterLink) throws LuanException {
+	Closure(LuanStateImpl luan,FnDef fnDef) throws LuanException {
 		this.fnDef = fnDef;
-		this.mtGetterLink = mtGetterLink;
 		UpValue.Getter[] upValueGetters = fnDef.upValueGetters;
 		this.upValues = new UpValue[upValueGetters.length];
 		for( int i=0; i<upValues.length; i++ ) {
@@ -33,14 +31,9 @@
 	}
 
 	@Override public void deepenClone(Closure clone,DeepCloner cloner) {
-		clone.mtGetterLink = cloner.deepClone(mtGetterLink);
 		clone.upValues = cloner.deepClone(upValues);
 	}
 
-	MtGetterLink mtGetterLink() {
-		return mtGetterLink;
-	}
-
 	UpValue[] upValues() {
 		return upValues;
 	}
--- a/core/src/luan/impl/FnDef.java	Tue Jul 08 02:04:24 2014 +0000
+++ b/core/src/luan/impl/FnDef.java	Tue Jul 08 07:04:47 2014 +0000
@@ -36,7 +36,7 @@
 	}
 
 	@Override public Object eval(LuanStateImpl luan) throws LuanException {
-		return new Closure(luan,this,luan.mtGetterLink());
+		return new Closure(luan,this);
 	}
 
 }
--- a/core/src/luan/impl/LuanCompiler.java	Tue Jul 08 02:04:24 2014 +0000
+++ b/core/src/luan/impl/LuanCompiler.java	Tue Jul 08 07:04:47 2014 +0000
@@ -25,27 +25,18 @@
 		}
 		FnDef fnDef = parse(luan,parser,allowExpr);
 		final LuanStateImpl luanImpl = (LuanStateImpl)luan;
-		MtGetterLink mtGetterLink = (MtGetterLink)env.get("_MTG");
-		final Closure c = new Closure(luanImpl,fnDef,mtGetterLink);
+		final Closure c = new Closure(luanImpl,fnDef);
+		if( passedEnv )
+			return c;
 		final LuanTable ENV = env;
-		if( passedEnv ) {
-			return new LuanFunction() {
-				@Override public Object call(LuanState luan,Object[] args) throws LuanException {
-					Object rtn = c.call(luan,args);
-					ENV.put("_MTG",luanImpl.mtGetterLink);
-					return rtn;
-				}
-			};
-		} else {
-			return new LuanFunction() {
-				@Override public Object call(LuanState luan,Object[] args) throws LuanException {
-					Object rtn = c.call(luan,args);
-					if( rtn instanceof Object[] && ((Object[])rtn).length==0 )
-						rtn = ENV;
-					return rtn;
-				}
-			};
-		}
+		return new LuanFunction() {
+			@Override public Object call(LuanState luan,Object[] args) throws LuanException {
+				Object rtn = c.call(luan,args);
+				if( rtn instanceof Object[] && ((Object[])rtn).length==0 )
+					rtn = ENV;
+				return rtn;
+			}
+		};
 	}
 
 	private static FnDef parse(LuanState luan,LuanParser parser,boolean allowExpr) throws LuanException {
--- a/core/src/luan/impl/LuanStateImpl.java	Tue Jul 08 02:04:24 2014 +0000
+++ b/core/src/luan/impl/LuanStateImpl.java	Tue Jul 08 07:04:47 2014 +0000
@@ -8,7 +8,6 @@
 import luan.LuanState;
 import luan.LuanTable;
 import luan.LuanFunction;
-import luan.MetatableGetter;
 import luan.LuanException;
 import luan.LuanElement;
 import luan.DeepCloner;
@@ -21,7 +20,6 @@
 		final Closure closure;
 		final Object[] stack;
 		final Object[] varArgs;
-		MtGetterLink mtGetterLink;
 		UpValue[] downValues = null;
 
 		Frame( Frame previousFrame, Closure closure, int stackSize, Object[] varArgs) {
@@ -29,7 +27,6 @@
 			this.closure = closure;
 			this.stack = new Object[stackSize];
 			this.varArgs = varArgs;
-			this.mtGetterLink = closure.mtGetterLink();
 		}
 
 		void stackClear(int start,int end) {
@@ -54,17 +51,11 @@
 				downValues[index] = new UpValue(stack,index);
 			return downValues[index];
 		}
-
-		void addMetatableGetter(MetatableGetter mg) {
-			if( mtGetterLink==null || !mtGetterLink.contains(mg) )
-				mtGetterLink = new MtGetterLink(mg,mtGetterLink);
-		}
 	}
 
 	private Frame frame = null;
 	Object returnValues;
 	Closure tailFn;
-	MtGetterLink mtGetterLink = null;
 
 	LuanStateImpl() {}
 
@@ -89,7 +80,6 @@
 	void popFrame() {
 		returnValues = LuanFunction.NOTHING;
 		tailFn = null;
-		mtGetterLink = frame.mtGetterLink;
 		frame = frame.previousFrame;
 	}
 
@@ -123,21 +113,4 @@
 		return (LuanTable)frame.closure.upValues()[0].get();
 	}
 
-	MtGetterLink mtGetterLink() {
-		return frame==null ? null : frame.mtGetterLink;
-	}
-
-	@Override public LuanTable getMetatable(Object obj,MetatableGetter beforeThis) {
-		if( obj instanceof LuanTable ) {
-			LuanTable table = (LuanTable)obj;
-			return table.getMetatable();
-		}
-		MtGetterLink mtGetterLink = mtGetterLink();
-		return mtGetterLink==null ? null : mtGetterLink.getMetatable(obj,beforeThis);
-	}
-
-	@Override public void addMetatableGetter(MetatableGetter mg) {
-		frame.addMetatableGetter(mg);
-	}
-
 }
--- a/core/src/luan/impl/MtGetterLink.java	Tue Jul 08 02:04:24 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-package luan.impl;
-
-import luan.MetatableGetter;
-import luan.LuanTable;
-import luan.DeepCloneable;
-import luan.DeepCloner;
-
-
-final class MtGetterLink implements DeepCloneable<MtGetterLink> {
-	private MetatableGetter mg;
-	private MtGetterLink next;
-
-	private MtGetterLink() {}
-
-	MtGetterLink(MetatableGetter mg,MtGetterLink next) {
-		this.mg = mg;
-		this.next = next;
-	}
-
-	LuanTable getMetatable(Object obj,MetatableGetter beforeThis) {
-		if( beforeThis != null ) {
-			if( beforeThis==mg )
-				beforeThis = null;
-		} else {
-			LuanTable mt = mg.getMetatable(obj);
-			if( mt != null )
-				return mt;
-		}
-		return next==null ? null : next.getMetatable(obj,beforeThis);
-	}
-
-	boolean contains(MetatableGetter mg) {
-		return this.mg==mg || next!=null && next.contains(mg);
-	}
-
-	@Override public MtGetterLink shallowClone() {
-		return new MtGetterLink();
-	}
-
-	@Override public void deepenClone(MtGetterLink clone,DeepCloner cloner) {
-		clone.mg = cloner.deepClone(mg);
-		clone.next = cloner.deepClone(next);
-	}
-}
--- a/core/src/luan/modules/JavaLuan.java	Tue Jul 08 02:04:24 2014 +0000
+++ b/core/src/luan/modules/JavaLuan.java	Tue Jul 08 07:04:47 2014 +0000
@@ -19,12 +19,10 @@
 import luan.Luan;
 import luan.LuanState;
 import luan.LuanTable;
-import luan.MetatableGetter;
 import luan.LuanException;
 import luan.LuanFunction;
 import luan.LuanJavaFunction;
 import luan.LuanElement;
-import luan.DeepCloner;
 
 
 public final class JavaLuan {
@@ -32,7 +30,6 @@
 	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() );
 			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 );
@@ -72,104 +69,64 @@
 		}
 	}
 
-	public static class MyMetatableGetter implements MetatableGetter {
-		private LuanTable metatable;
-
-		private MyMetatableGetter() {
-			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 );
-		}
-
-		private MyMetatableGetter(MyMetatableGetter mmg) {}
-
-		@Override public MetatableGetter shallowClone() {
-			return new MyMetatableGetter(this);
-		}
-
-		@Override public void deepenClone(MetatableGetter c,DeepCloner cloner) {
-			MyMetatableGetter clone = (MyMetatableGetter)c;
-			clone.metatable = cloner.deepClone(metatable);
-		}
-
-		@Override public LuanTable getMetatable(Object obj) {
-			if( obj==null )
-				return null;
-			return metatable;
-		}
-
-		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( 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);
+	public static Object __index(LuanState luan,Object obj,Object key) throws LuanException {
+		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));
 							}
-						}
-					} 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);
+							return new AmbiguousJavaFunction(fns);
 						}
 					}
-				}
-				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;
-				if( "instanceof".equals(name) ) {
-					return new LuanJavaFunction(instanceOf,new InstanceOf(obj));
+				} else if( "assert".equals(name) ) {
+					return new LuanJavaFunction(assertClass,new AssertClass(cls));
 				} else {
-					List<Member> members = getMembers(cls,name);
+					List<Member> members = getStaticMembers(cls,name);
 					if( !members.isEmpty() ) {
-						return member(obj,members);
+						return member(null,members);
 					}
 				}
 			}
-			return null;
+			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;
+			if( "instanceof".equals(name) ) {
+				return new LuanJavaFunction(instanceOf,new InstanceOf(obj));
+			} else {
+				List<Member> members = getMembers(cls,name);
+				if( !members.isEmpty() ) {
+					if( name.equals("getClass") && !isLoaded(luan) )
+						return null;  // security
+					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/PackageLuan.java	Tue Jul 08 02:04:24 2014 +0000
+++ b/core/src/luan/modules/PackageLuan.java	Tue Jul 08 07:04:47 2014 +0000
@@ -11,7 +11,6 @@
 import luan.LuanJavaFunction;
 import luan.LuanElement;
 import luan.LuanException;
-import luan.MetatableGetter;
 
 
 public final class PackageLuan {
@@ -108,12 +107,6 @@
 				}
 			}
 		}
-		if( mod instanceof LuanTable ) {
-			LuanTable modTbl = (LuanTable)mod;
-			MetatableGetter mg = (MetatableGetter)modTbl.get(MetatableGetter.KEY);
-			if( mg != null )
-				luan.addMetatableGetter(mg);
-		}
 		return mod;
 	}
 
--- a/core/src/luan/modules/StringLuan.java	Tue Jul 08 02:04:24 2014 +0000
+++ b/core/src/luan/modules/StringLuan.java	Tue Jul 08 07:04:47 2014 +0000
@@ -9,8 +9,6 @@
 import luan.LuanJavaFunction;
 import luan.LuanElement;
 import luan.LuanException;
-import luan.MetatableGetter;
-import luan.DeepCloner;
 
 
 public final class StringLuan {
@@ -18,7 +16,6 @@
 	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) );
 			try {
 				add( module, "to_binary", String.class );
 				add( module, "to_integers", String.class );
@@ -45,40 +42,10 @@
 		t.put( method, new LuanJavaFunction(StringLuan.class.getMethod(method,parameterTypes),null) );
 	}
 
-	public static class MyMetatableGetter implements MetatableGetter {
-		private LuanTable module;
-		private LuanTable metatable;
-
-		private MyMetatableGetter(LuanTable module) {
-			this.module = module;
-			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);
-			}
-		}
-
-		private MyMetatableGetter(MyMetatableGetter mmg) {}
-
-		@Override public MetatableGetter shallowClone() {
-			return new MyMetatableGetter(this);
-		}
-
-		@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) {
-			return obj instanceof String ? metatable : null;
-		}
-
-		public Object __index(LuanState luan,final String s,Object key) throws LuanException {
-			Object obj = module.get(key);
+	public static Object __index(LuanState luan,final String s,Object key) throws LuanException {
+		LuanTable mod = (LuanTable)PackageLuan.loaded(luan).get("String");
+		if( mod!=null ) {
+			Object obj = mod.get(key);
 			if( obj instanceof LuanFunction ) {
 				final LuanFunction fn = (LuanFunction)obj;
 				return new LuanFunction() {
@@ -90,15 +57,8 @@
 					}
 				};
 			}
-			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});
 		}
+		return null;
 	}
 
 	static int start(String s,int i) {
Binary file dist/luan-core-trunk.jar has changed
Binary file dist/luan-logging-trunk.jar has changed
Binary file dist/luan-web-trunk.jar has changed
--- a/web/src/luan/modules/web/web_run.luan	Tue Jul 08 02:04:24 2014 +0000
+++ b/web/src/luan/modules/web/web_run.luan	Tue Jul 08 07:04:47 2014 +0000
@@ -1,5 +1,6 @@
 import "Io"
 import "web/Http"
+import "String"
 
 local function lines(s)
 	local matcher = String.gmatch(s,"([^\n]*)\n|([^\n])+$")