comparison core/src/luan/modules/JavaLuan.java @ 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 75750ceb45ee
comparison
equal deleted inserted replaced
196:be0275bda373 197:4c96cb73dd93
30 public final class JavaLuan { 30 public final class JavaLuan {
31 31
32 public static final LuanFunction LOADER = new LuanFunction() { 32 public static final LuanFunction LOADER = new LuanFunction() {
33 @Override public Object call(LuanState luan,Object[] args) { 33 @Override public Object call(LuanState luan,Object[] args) {
34 LuanTable module = new LuanTable(); 34 LuanTable module = new LuanTable();
35 module.put( MetatableGetter.KEY, mg ); 35 MyMetatableGetter mmg = new MyMetatableGetter();
36 mmg.init();
37 module.put( MetatableGetter.KEY, mmg );
36 try { 38 try {
37 module.put( "class", new LuanJavaFunction(JavaLuan.class.getMethod("getClass",LuanState.class,String.class),null) ); 39 module.put( "class", new LuanJavaFunction(JavaLuan.class.getMethod("getClass",LuanState.class,String.class),null) );
38 add( module, "proxy", LuanState.class, Static.class, LuanTable.class, Object.class ); 40 add( module, "proxy", LuanState.class, Static.class, LuanTable.class, Object.class );
39 } catch(NoSuchMethodException e) { 41 } catch(NoSuchMethodException e) {
40 throw new RuntimeException(e); 42 throw new RuntimeException(e);
65 } catch(NoSuchMethodException e) { 67 } catch(NoSuchMethodException e) {
66 throw new RuntimeException(e); 68 throw new RuntimeException(e);
67 } 69 }
68 } 70 }
69 71
70 private static final LuanTable mt = new LuanTable(); 72 public static class MyMetatableGetter implements MetatableGetter {
71 static { 73 private LuanTable metatable;
72 add( mt, "__index", LuanState.class, Object.class, Object.class ); 74
73 add( mt, "__newindex", LuanState.class, Object.class, Object.class, Object.class ); 75 private MyMetatableGetter() {}
74 } 76
75 77 private void init() {
76 private static final MetatableGetter mg = new MetatableGetter() { 78 this.metatable = new LuanTable();
77 79 try {
78 public LuanTable getMetatable(Object obj) { 80 metatable.put( "__index", new LuanJavaFunction(
81 MyMetatableGetter.class.getMethod( "__index", LuanState.class, Object.class, Object.class ), this
82 ) );
83 } catch(NoSuchMethodException e) {
84 throw new RuntimeException(e);
85 }
86 add( metatable, "__newindex", LuanState.class, Object.class, Object.class, Object.class );
87 }
88
89 @Override public MetatableGetter shallowClone() {
90 return new MyMetatableGetter();
91 }
92
93 @Override public void deepenClone(MetatableGetter c,DeepCloner cloner) {
94 MyMetatableGetter clone = (MyMetatableGetter)c;
95 clone.metatable = cloner.deepClone(metatable);
96 }
97
98 @Override public LuanTable getMetatable(Object obj) {
79 if( obj==null ) 99 if( obj==null )
80 return null; 100 return null;
81 return mt; 101 return metatable;
82 } 102 }
83 103
84 @Override public MetatableGetter shallowClone() { 104 public Object __index(LuanState luan,Object obj,Object key) throws LuanException {
85 return this; 105 LuanTable mt = luan.getMetatable(obj,this);
86 } 106 if( mt != null ) {
87 @Override public void deepenClone(MetatableGetter clone,DeepCloner cloner) {} 107 Object h = mt.get("__index");
88 }; 108 if( h instanceof LuanFunction ) {
89 109 LuanFunction fn = (LuanFunction)h;
90 public static Object __index(LuanState luan,Object obj,Object key) throws LuanException { 110 Object rtn = Luan.first(luan.call(fn,new Object[]{obj,key}));
91 LuanTable mt = luan.getMetatable(obj,mg); 111 if( rtn != null )
92 if( mt != null ) { 112 return rtn;
93 Object h = mt.get("__index"); 113 }
94 if( h instanceof LuanFunction ) { 114 }
95 LuanFunction fn = (LuanFunction)h; 115 if( obj instanceof Static ) {
96 Object rtn = Luan.first(luan.call(fn,new Object[]{obj,key})); 116 if( key instanceof String ) {
97 if( rtn != null ) 117 String name = (String)key;
98 return rtn; 118 Static st = (Static)obj;
99 } 119 Class cls = st.cls;
100 } 120 if( "class".equals(name) ) {
101 if( obj instanceof Static ) { 121 return cls;
122 } else if( "new".equals(name) ) {
123 Constructor<?>[] constructors = cls.getConstructors();
124 if( constructors.length > 0 ) {
125 if( constructors.length==1 ) {
126 return new LuanJavaFunction(constructors[0],null);
127 } else {
128 List<LuanJavaFunction> fns = new ArrayList<LuanJavaFunction>();
129 for( Constructor constructor : constructors ) {
130 fns.add(new LuanJavaFunction(constructor,null));
131 }
132 return new AmbiguousJavaFunction(fns);
133 }
134 }
135 } else if( "assert".equals(name) ) {
136 return new LuanJavaFunction(assertClass,new AssertClass(cls));
137 } else {
138 List<Member> members = getStaticMembers(cls,name);
139 if( !members.isEmpty() ) {
140 return member(null,members);
141 }
142 }
143 }
144 throw luan.exception("invalid member '"+key+"' for: "+obj);
145 }
146 Class cls = obj.getClass();
147 if( cls.isArray() ) {
148 if( "length".equals(key) ) {
149 return Array.getLength(obj);
150 }
151 Integer i = Luan.asInteger(key);
152 if( i != null ) {
153 return Array.get(obj,i);
154 }
155 throw luan.exception("invalid member '"+key+"' for java array: "+obj);
156 }
102 if( key instanceof String ) { 157 if( key instanceof String ) {
103 String name = (String)key; 158 String name = (String)key;
104 Static st = (Static)obj; 159 if( "instanceof".equals(name) ) {
105 Class cls = st.cls; 160 return new LuanJavaFunction(instanceOf,new InstanceOf(obj));
106 if( "class".equals(name) ) { 161 } else {
107 return cls; 162 List<Member> members = getMembers(cls,name);
108 } else if( "new".equals(name) ) { 163 if( !members.isEmpty() ) {
109 Constructor<?>[] constructors = cls.getConstructors(); 164 return member(obj,members);
110 if( constructors.length > 0 ) {
111 if( constructors.length==1 ) {
112 return new LuanJavaFunction(constructors[0],null);
113 } else {
114 List<LuanJavaFunction> fns = new ArrayList<LuanJavaFunction>();
115 for( Constructor constructor : constructors ) {
116 fns.add(new LuanJavaFunction(constructor,null));
117 }
118 return new AmbiguousJavaFunction(fns);
119 }
120 } 165 }
121 } else if( "assert".equals(name) ) { 166 }
122 return new LuanJavaFunction(assertClass,new AssertClass(cls)); 167 }
123 } else { 168 return null;
124 List<Member> members = getStaticMembers(cls,name); 169 }
125 if( !members.isEmpty() ) {
126 return member(null,members);
127 }
128 }
129 }
130 throw luan.exception("invalid member '"+key+"' for: "+obj);
131 }
132 Class cls = obj.getClass();
133 if( cls.isArray() ) {
134 if( "length".equals(key) ) {
135 return Array.getLength(obj);
136 }
137 Integer i = Luan.asInteger(key);
138 if( i != null ) {
139 return Array.get(obj,i);
140 }
141 throw luan.exception("invalid member '"+key+"' for java array: "+obj);
142 }
143 if( key instanceof String ) {
144 String name = (String)key;
145 if( "instanceof".equals(name) ) {
146 return new LuanJavaFunction(instanceOf,new InstanceOf(obj));
147 } else {
148 List<Member> members = getMembers(cls,name);
149 if( !members.isEmpty() ) {
150 return member(obj,members);
151 }
152 }
153 }
154 // throw luan.exception("invalid member '"+key+"' for java object: "+obj);
155 return null;
156 } 170 }
157 171
158 private static Object member(Object obj,List<Member> members) throws LuanException { 172 private static Object member(Object obj,List<Member> members) throws LuanException {
159 try { 173 try {
160 if( members.size()==1 ) { 174 if( members.size()==1 ) {