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