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