Mercurial Hosting > luan
comparison core/src/luan/LuanTable.java @ 572:f1601a4ce1aa
fix stack when calling meta-methods
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 12 Jul 2015 21:34:23 -0600 |
parents | 473e456444ff |
children | 7c3ad6db8ac3 |
comparison
equal
deleted
inserted
replaced
571:cd944b010f25 | 572:f1601a4ce1aa |
---|---|
90 | 90 |
91 public List<Object> asList() { | 91 public List<Object> asList() { |
92 return list!=null ? list : Collections.emptyList(); | 92 return list!=null ? list : Collections.emptyList(); |
93 } | 93 } |
94 | 94 |
95 public String toString(LuanState luan) throws LuanException { | 95 public String toString(LuanBit bit) throws LuanException { |
96 Object h = getHandler("__to_string"); | 96 Object h = getHandler("__to_string"); |
97 if( h == null ) | 97 if( h == null ) |
98 return rawToString(); | 98 return rawToString(); |
99 if( h instanceof LuanMeta ) { | 99 if( h instanceof LuanMeta ) { |
100 LuanMeta meta = (LuanMeta)h; | 100 LuanMeta meta = (LuanMeta)h; |
101 return meta.__to_string(luan,this); | 101 return meta.__to_string(bit.luan,this); |
102 } | 102 } |
103 LuanFunction fn = luan.checkFunction(h); | 103 LuanFunction fn = bit.checkFunction(h); |
104 return luan.checkString( Luan.first( luan.call(fn,"__to_string",new Object[]{this}) ) ); | 104 return bit.checkString( Luan.first( bit.call(fn,"__to_string",new Object[]{this}) ) ); |
105 } | 105 } |
106 | 106 |
107 public String rawToString() { | 107 public String rawToString() { |
108 return "table: " + Integer.toHexString(hashCode()); | 108 return "table: " + Integer.toHexString(hashCode()); |
109 } | 109 } |
110 | 110 |
111 public Object get(LuanState luan,Object key) throws LuanException { | 111 public Object get(LuanBit bit,Object key) throws LuanException { |
112 Object value = rawGet(key); | 112 Object value = rawGet(key); |
113 if( value != null ) | 113 if( value != null ) |
114 return value; | 114 return value; |
115 Object h = getHandler("__index"); | 115 Object h = getHandler("__index"); |
116 if( h==null ) | 116 if( h==null ) |
117 return null; | 117 return null; |
118 if( h instanceof LuanFunction ) { | 118 if( h instanceof LuanFunction ) { |
119 LuanFunction fn = (LuanFunction)h; | 119 LuanFunction fn = (LuanFunction)h; |
120 return Luan.first(luan.call(fn,"__index",new Object[]{this,key})); | 120 return Luan.first(bit.call(fn,"__index",new Object[]{this,key})); |
121 } | 121 } |
122 if( h instanceof LuanMeta ) { | 122 if( h instanceof LuanMeta ) { |
123 LuanMeta meta = (LuanMeta)h; | 123 LuanMeta meta = (LuanMeta)h; |
124 return meta.__index(luan,this,key); | 124 return meta.__index(bit.luan,this,key); |
125 } | 125 } |
126 return index(luan.JAVA,h,key); | 126 return index(bit,h,key); |
127 } | 127 } |
128 | 128 |
129 public static Object index(LuanBit bit,Object obj,Object key) throws LuanException { | 129 public static Object index(LuanBit bit,Object obj,Object key) throws LuanException { |
130 LuanState luan = bit.luan; | |
131 if( obj instanceof LuanTable ) { | 130 if( obj instanceof LuanTable ) { |
132 LuanTable tbl = (LuanTable)obj; | 131 LuanTable tbl = (LuanTable)obj; |
133 return tbl.get(luan,key); | 132 return tbl.get(bit,key); |
134 } | 133 } |
135 if( obj != null && luan.hasJava() ) | 134 if( obj != null && bit.luan.hasJava() ) |
136 return JavaLuan.__index(bit,obj,key,false); | 135 return JavaLuan.__index(bit,obj,key,false); |
137 else if( bit.el==null ) | 136 else if( bit.el==null ) |
138 throw bit.exception( "attempt to index a " + Luan.type(obj) + " value" ); | 137 throw bit.exception( "attempt to index a " + Luan.type(obj) + " value" ); |
139 else | 138 else |
140 throw bit.exception( "attempt to index a " + Luan.type(obj) + " value in '"+bit.el.text()+"'" ); | 139 throw bit.exception( "attempt to index a " + Luan.type(obj) + " value in '"+bit.el.text()+"'" ); |
156 key = Double.valueOf(n.doubleValue()); | 155 key = Double.valueOf(n.doubleValue()); |
157 } | 156 } |
158 return map.get(key); | 157 return map.get(key); |
159 } | 158 } |
160 | 159 |
161 public void put(LuanState luan,Object key,Object value) throws LuanException { | 160 public void put(LuanBit bit,Object key,Object value) throws LuanException { |
162 Object h = getHandler("__new_index"); | 161 Object h = getHandler("__new_index"); |
163 if( h==null || rawGet(key)!=null ) { | 162 if( h==null || rawGet(key)!=null ) { |
164 rawPut(key,value); | 163 rawPut(key,value); |
165 return; | 164 return; |
166 } | 165 } |
167 if( h instanceof LuanFunction ) { | 166 if( h instanceof LuanFunction ) { |
168 LuanFunction fn = (LuanFunction)h; | 167 LuanFunction fn = (LuanFunction)h; |
169 luan.call(fn,"__new_index",new Object[]{this,key,value}); | 168 bit.call(fn,"__new_index",new Object[]{this,key,value}); |
170 return; | 169 return; |
171 } | 170 } |
172 if( h instanceof LuanMeta ) { | 171 if( h instanceof LuanMeta ) { |
173 LuanMeta meta = (LuanMeta)h; | 172 LuanMeta meta = (LuanMeta)h; |
174 meta.__new_index(luan,this,key,value); | 173 meta.__new_index(bit.luan,this,key,value); |
175 return; | 174 return; |
176 } | 175 } |
177 if( h instanceof LuanTable ) { | 176 if( h instanceof LuanTable ) { |
178 LuanTable tbl = (LuanTable)h; | 177 LuanTable tbl = (LuanTable)h; |
179 tbl.put(luan,key,value); | 178 tbl.put(bit,key,value); |
180 return; | 179 return; |
181 } | 180 } |
182 throw luan.exception("invalid type "+Luan.type(h)+" for metamethod __new_index"); | 181 throw bit.exception("invalid type "+Luan.type(h)+" for metamethod __new_index"); |
183 } | 182 } |
184 | 183 |
185 public void rawPut(Object key,Object val) { | 184 public void rawPut(Object key,Object val) { |
186 Integer iT = Luan.asInteger(key); | 185 Integer iT = Luan.asInteger(key); |
187 if( iT != null ) { | 186 if( iT != null ) { |
261 | 260 |
262 public void rawSort(Comparator<Object> cmp) { | 261 public void rawSort(Comparator<Object> cmp) { |
263 Collections.sort(list(),cmp); | 262 Collections.sort(list(),cmp); |
264 } | 263 } |
265 | 264 |
266 public int length(LuanState luan) throws LuanException { | 265 public int length(LuanBit bit) throws LuanException { |
267 Object h = getHandler("__len"); | 266 Object h = getHandler("__len"); |
268 if( h != null ) { | 267 if( h != null ) { |
269 LuanFunction fn = luan.checkFunction(h); | 268 LuanFunction fn = bit.checkFunction(h); |
270 return (Integer)Luan.first(luan.call(fn,"__len",new Object[]{this})); | 269 return (Integer)Luan.first(bit.call(fn,"__len",new Object[]{this})); |
271 } | 270 } |
272 return rawLength(); | 271 return rawLength(); |
273 } | 272 } |
274 | 273 |
275 public int rawLength() { | 274 public int rawLength() { |
276 return list==null ? 0 : list.size(); | 275 return list==null ? 0 : list.size(); |
277 } | 276 } |
278 | 277 |
279 public Iterable<Map.Entry<Object,Object>> iterable(LuanState luan) throws LuanException { | 278 public Iterable<Map.Entry<Object,Object>> iterable(LuanBit bit) throws LuanException { |
280 final Iterator<Map.Entry<Object,Object>> iter = iterator(luan); | 279 final Iterator<Map.Entry<Object,Object>> iter = iterator(bit); |
281 return new Iterable<Map.Entry<Object,Object>>() { | 280 return new Iterable<Map.Entry<Object,Object>>() { |
282 public Iterator<Map.Entry<Object,Object>> iterator() { | 281 public Iterator<Map.Entry<Object,Object>> iterator() { |
283 return iter; | 282 return iter; |
284 } | 283 } |
285 }; | 284 }; |
292 return iter; | 291 return iter; |
293 } | 292 } |
294 }; | 293 }; |
295 } | 294 } |
296 | 295 |
297 public Iterator<Map.Entry<Object,Object>> iterator(final LuanState luan) throws LuanException { | 296 public Iterator<Map.Entry<Object,Object>> iterator(final LuanBit bit) throws LuanException { |
298 if( getHandler("__pairs") == null ) | 297 if( getHandler("__pairs") == null ) |
299 return rawIterator(); | 298 return rawIterator(); |
300 final LuanFunction fn = pairs(luan); | 299 final LuanFunction fn = pairs(bit); |
301 return new Iterator<Map.Entry<Object,Object>>() { | 300 return new Iterator<Map.Entry<Object,Object>>() { |
302 private Map.Entry<Object,Object> next = getNext(); | 301 private Map.Entry<Object,Object> next = getNext(); |
303 | 302 |
304 private Map.Entry<Object,Object> getNext() { | 303 private Map.Entry<Object,Object> getNext() { |
305 try { | 304 try { |
306 Object obj = luan.call(fn); | 305 Object obj = bit.call(fn,null,LuanFunction.NOTHING); |
307 if( obj==null ) | 306 if( obj==null ) |
308 return null; | 307 return null; |
309 Object[] a = (Object[])obj; | 308 Object[] a = (Object[])obj; |
310 if( a.length == 0 || a[0]==null ) | 309 if( a.length == 0 || a[0]==null ) |
311 return null; | 310 return null; |
329 throw new UnsupportedOperationException(); | 328 throw new UnsupportedOperationException(); |
330 } | 329 } |
331 }; | 330 }; |
332 } | 331 } |
333 | 332 |
334 public LuanFunction pairs(final LuanState luan) throws LuanException { | 333 public LuanFunction pairs(LuanBit bit) throws LuanException { |
335 Object h = getHandler("__pairs"); | 334 Object h = getHandler("__pairs"); |
336 if( h != null ) { | 335 if( h != null ) { |
337 if( h instanceof LuanFunction ) { | 336 if( h instanceof LuanFunction ) { |
338 Object obj = Luan.first(luan.call((LuanFunction)h,"__pairs",new Object[]{this})); | 337 Object obj = Luan.first(bit.call((LuanFunction)h,"__pairs",new Object[]{this})); |
339 if( !(obj instanceof LuanFunction) ) | 338 if( !(obj instanceof LuanFunction) ) |
340 throw luan.exception( "metamethod __pairs should return function but returned " + Luan.type(obj) ); | 339 throw bit.exception( "metamethod __pairs should return function but returned " + Luan.type(obj) ); |
341 return (LuanFunction)obj; | 340 return (LuanFunction)obj; |
342 } | 341 } |
343 if( h instanceof LuanMeta ) { | 342 if( h instanceof LuanMeta ) { |
344 LuanMeta meta = (LuanMeta)h; | 343 LuanMeta meta = (LuanMeta)h; |
345 return meta.__pairs(luan,this); | 344 return meta.__pairs(bit.luan,this); |
346 } | 345 } |
347 throw luan.exception( "invalid type of metamethod __pairs: " + Luan.type(h) ); | 346 throw bit.exception( "invalid type of metamethod __pairs: " + Luan.type(h) ); |
348 } | 347 } |
349 return rawPairs(); | 348 return rawPairs(); |
350 } | 349 } |
351 | 350 |
352 private LuanFunction rawPairs() { | 351 private LuanFunction rawPairs() { |
435 | 434 |
436 private Map<Object,Object> newMap() { | 435 private Map<Object,Object> newMap() { |
437 return new LinkedHashMap<Object,Object>(); | 436 return new LinkedHashMap<Object,Object>(); |
438 } | 437 } |
439 | 438 |
440 public boolean isSet(LuanState luan) throws LuanException { | 439 public boolean isSet(LuanBit bit) throws LuanException { |
441 for( Map.Entry<Object,Object> entry : iterable(luan) ) { | 440 for( Map.Entry<Object,Object> entry : iterable(bit) ) { |
442 if( !entry.getValue().equals(Boolean.TRUE) ) | 441 if( !entry.getValue().equals(Boolean.TRUE) ) |
443 return false; | 442 return false; |
444 } | 443 } |
445 return true; | 444 return true; |
446 } | 445 } |
447 | 446 |
448 public Set<Object> asSet(LuanState luan) throws LuanException { | 447 public Set<Object> asSet(LuanBit bit) throws LuanException { |
449 Set<Object> set = new HashSet<Object>(); | 448 Set<Object> set = new HashSet<Object>(); |
450 for( Map.Entry<Object,Object> entry : iterable(luan) ) { | 449 for( Map.Entry<Object,Object> entry : iterable(bit) ) { |
451 set.add(entry.getKey()); | 450 set.add(entry.getKey()); |
452 } | 451 } |
453 return set; | 452 return set; |
454 } | 453 } |
455 | 454 |
456 public Map<Object,Object> asMap(LuanState luan) throws LuanException { | 455 public Map<Object,Object> asMap(LuanBit bit) throws LuanException { |
457 Map<Object,Object> map = newMap(); | 456 Map<Object,Object> map = newMap(); |
458 for( Map.Entry<Object,Object> entry : iterable(luan) ) { | 457 for( Map.Entry<Object,Object> entry : iterable(bit) ) { |
459 map.put(entry.getKey(),entry.getValue()); | 458 map.put(entry.getKey(),entry.getValue()); |
460 } | 459 } |
461 return map; | 460 return map; |
462 } | 461 } |
463 | 462 |