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