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