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