Mercurial Hosting > luan
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) {