comparison core/src/luan/LuanTable.java @ 432:d9df6d6cb927

finish fixing LuanTable to use metatables
author Franklin Schmidt <fschmidt@gmail.com>
date Sat, 02 May 2015 23:41:59 -0600
parents 3ffe8ba5b297
children c6bcb8859b93
comparison
equal deleted inserted replaced
431:3ffe8ba5b297 432:d9df6d6cb927
13 import java.util.HashSet; 13 import java.util.HashSet;
14 import java.util.IdentityHashMap; 14 import java.util.IdentityHashMap;
15 import java.util.regex.Pattern; 15 import java.util.regex.Pattern;
16 16
17 17
18 public final class LuanTable implements Iterable<Map.Entry<Object,Object>>, DeepCloneable<LuanTable> { 18 public final class LuanTable implements DeepCloneable<LuanTable> {
19 private Map<Object,Object> map = null; 19 private Map<Object,Object> map = null;
20 private List<Object> list = null; 20 private List<Object> list = null;
21 private LuanTable metatable = null; 21 private LuanTable metatable = null;
22 private boolean hasJava = false; 22 private boolean hasJava = false;
23 23
24 public LuanTable() {} 24 public LuanTable() {}
25 25
26 public LuanTable(List<Object> list) { 26 public LuanTable(List<Object> list) {
27 this.list = list; 27 int n = list.size();
28 this.map = newMap(); 28 for( int i=0; i<n; i++ ) {
29 map.put("n",list.size()); 29 Object val = list.get(i);
30 for( int i=0; i<list.size(); i++ ) { 30 if( val != null )
31 if( list.get(i) == null ) { 31 rawPut(i+1,val);
32 listToMap(i); 32 }
33 break; 33 }
34 } 34
35 public LuanTable(Map<Object,Object> map) {
36 for( Map.Entry<Object,Object> entry : map.entrySet() ) {
37 Object key = entry.getKey();
38 Object value = entry.getValue();
39 if( key != null && value != null )
40 rawPut(key,value);
41 }
42 }
43
44 public LuanTable(Set<Object> set) {
45 for( Object el : set ) {
46 if( el != null )
47 rawPut(el,Boolean.TRUE);
35 } 48 }
36 } 49 }
37 50
38 public LuanTable(LuanTable tbl) { 51 public LuanTable(LuanTable tbl) {
39 if( tbl.map != null && !tbl.map.isEmpty() ) 52 if( tbl.map != null && !tbl.map.isEmpty() )
40 this.map = new LinkedHashMap<Object,Object>(tbl.map); 53 this.map = new LinkedHashMap<Object,Object>(tbl.map);
41 if( tbl.length() > 0 ) 54 if( tbl.rawLength() > 0 )
42 this.list = new ArrayList<Object>(tbl.list); 55 this.list = new ArrayList<Object>(tbl.list);
43 this.metatable = tbl.metatable; 56 this.metatable = tbl.metatable;
44 } 57 }
45 58
46 @Override public LuanTable shallowClone() { 59 @Override public LuanTable shallowClone() {
221 throw new IllegalArgumentException("can't insert a nil value"); 234 throw new IllegalArgumentException("can't insert a nil value");
222 list().add(pos-1,value); 235 list().add(pos-1,value);
223 mapToList(); 236 mapToList();
224 } 237 }
225 238
226 public void rawAdd(Object value) {
227 if( value==null )
228 throw new IllegalArgumentException("can't add a nil value");
229 list().add(value);
230 mapToList();
231 }
232
233 public Object rawRemove(int pos) { 239 public Object rawRemove(int pos) {
234 return list().remove(pos-1); 240 return list().remove(pos-1);
235 } 241 }
236 242
237 public void rawSort(Comparator<Object> cmp) { 243 public void rawSort(Comparator<Object> cmp) {
238 Collections.sort(list(),cmp); 244 Collections.sort(list(),cmp);
239 } 245 }
240 246
241 public int length() { 247 public int length(LuanState luan) throws LuanException {
248 Object h = getHandler("__len");
249 if( h != null ) {
250 LuanFunction fn = luan.checkFunction(h);
251 return (Integer)Luan.first(luan.call(fn,"__len",new Object[]{this}));
252 }
253 return rawLength();
254 }
255
256 public int rawLength() {
242 return list==null ? 0 : list.size(); 257 return list==null ? 0 : list.size();
243 } 258 }
244 259
245 @Override public Iterator<Map.Entry<Object,Object>> iterator() { 260 public Iterable<Map.Entry<Object,Object>> iterable(LuanState luan) throws LuanException {
261 final Iterator<Map.Entry<Object,Object>> iter = iterator(luan);
262 return new Iterable<Map.Entry<Object,Object>>() {
263 public Iterator<Map.Entry<Object,Object>> iterator() {
264 return iter;
265 }
266 };
267 }
268
269 public Iterator<Map.Entry<Object,Object>> iterator(final LuanState luan) throws LuanException {
270 if( getHandler("__pairs") == null )
271 return rawIterator();
272 final LuanFunction fn = pairs(luan);
273 return new Iterator<Map.Entry<Object,Object>>() {
274 private Map.Entry<Object,Object> next = getNext();
275
276 private Map.Entry<Object,Object> getNext() {
277 try {
278 Object obj = luan.call(fn);
279 if( obj==null )
280 return null;
281 Object[] a = (Object[])obj;
282 if( a.length == 0 )
283 return null;
284 return new AbstractMap.SimpleEntry<Object,Object>(a[0],a[1]);
285 } catch(LuanException e) {
286 throw new LuanRuntimeException(e);
287 }
288 }
289
290 public boolean hasNext() {
291 return next != null;
292 }
293
294 public Map.Entry<Object,Object> next() {
295 Map.Entry<Object,Object> rtn = next;
296 next = getNext();
297 return rtn;
298 }
299
300 public void remove() {
301 throw new UnsupportedOperationException();
302 }
303 };
304 }
305
306 public LuanFunction pairs(final LuanState luan) throws LuanException {
307 Object h = getHandler("__pairs");
308 if( h != null ) {
309 if( h instanceof LuanFunction ) {
310 Object obj = Luan.first(luan.call((LuanFunction)h,"__pairs",new Object[]{this}));
311 if( !(obj instanceof LuanFunction) )
312 throw luan.exception( "metamethod __pairs should return function but returned " + Luan.type(obj) );
313 return (LuanFunction)obj;
314 }
315 if( h instanceof LuanMeta ) {
316 LuanMeta meta = (LuanMeta)h;
317 return meta.__pairs(luan,this);
318 }
319 throw luan.exception( "invalid type of metamethod __pairs: " + Luan.type(h) );
320 }
321 return rawPairs();
322 }
323
324 private LuanFunction rawPairs() {
325 return new LuanFunction() {
326 final Iterator<Map.Entry<Object,Object>> iter = rawIterator();
327
328 @Override public Object[] call(LuanState luan,Object[] args) {
329 if( !iter.hasNext() )
330 return LuanFunction.NOTHING;
331 Map.Entry<Object,Object> entry = iter.next();
332 return new Object[]{entry.getKey(),entry.getValue()};
333 }
334 };
335 }
336
337 public Iterator<Map.Entry<Object,Object>> rawIterator() {
246 if( list == null ) { 338 if( list == null ) {
247 if( map == null ) 339 if( map == null )
248 return Collections.<Map.Entry<Object,Object>>emptyList().iterator(); 340 return Collections.<Map.Entry<Object,Object>>emptyList().iterator();
249 return map.entrySet().iterator(); 341 return map.entrySet().iterator();
250 } 342 }
251 if( map == null ) 343 if( map == null )
252 return listIterator(); 344 return listIterator();
253 return new Iterator<Map.Entry<Object,Object>>() { 345 return new Iterator<Map.Entry<Object,Object>>() {
254 Iterator<Map.Entry<Object,Object>> iter = listIterator(); 346 Iterator<Map.Entry<Object,Object>> iter = listIterator();
255 boolean isList = true; 347 boolean isList = true;
348
256 public boolean hasNext() { 349 public boolean hasNext() {
257 boolean b = iter.hasNext(); 350 boolean b = iter.hasNext();
258 if( !b && isList ) { 351 if( !b && isList ) {
259 iter = map.entrySet().iterator(); 352 iter = map.entrySet().iterator();
260 isList = false; 353 isList = false;
261 b = iter.hasNext(); 354 b = iter.hasNext();
262 } 355 }
263 return b; 356 return b;
264 } 357 }
358
265 public Map.Entry<Object,Object> next() { 359 public Map.Entry<Object,Object> next() {
266 return iter.next(); 360 return iter.next();
267 } 361 }
362
268 public void remove() { 363 public void remove() {
269 throw new UnsupportedOperationException(); 364 throw new UnsupportedOperationException();
270 } 365 }
271 }; 366 };
272 } 367 }
274 private Iterator<Map.Entry<Object,Object>> listIterator() { 369 private Iterator<Map.Entry<Object,Object>> listIterator() {
275 if( list == null ) 370 if( list == null )
276 return Collections.<Map.Entry<Object,Object>>emptyList().iterator(); 371 return Collections.<Map.Entry<Object,Object>>emptyList().iterator();
277 final ListIterator iter = list.listIterator(); 372 final ListIterator iter = list.listIterator();
278 return new Iterator<Map.Entry<Object,Object>>() { 373 return new Iterator<Map.Entry<Object,Object>>() {
374
279 public boolean hasNext() { 375 public boolean hasNext() {
280 return iter.hasNext(); 376 return iter.hasNext();
281 } 377 }
378
282 public Map.Entry<Object,Object> next() { 379 public Map.Entry<Object,Object> next() {
283 Double key = Double.valueOf(iter.nextIndex()+1); 380 Integer key = iter.nextIndex()+1;
284 return new AbstractMap.SimpleEntry<Object,Object>(key,iter.next()); 381 return new AbstractMap.SimpleEntry<Object,Object>(key,iter.next());
285 } 382 }
383
286 public void remove() { 384 public void remove() {
287 throw new UnsupportedOperationException(); 385 throw new UnsupportedOperationException();
288 } 386 }
289 }; 387 };
290 } 388 }
302 public void setMetatable(LuanTable metatable) { 400 public void setMetatable(LuanTable metatable) {
303 this.metatable = metatable; 401 this.metatable = metatable;
304 } 402 }
305 403
306 public Object getHandler(String op) { 404 public Object getHandler(String op) {
307 LuanTable t = getMetatable(); 405 return metatable==null ? null : metatable.rawGet(op);
308 return t==null ? null : t.rawGet(op);
309 } 406 }
310 407
311 public boolean hasJava() { 408 public boolean hasJava() {
312 return hasJava; 409 return hasJava;
313 } 410 }
321 418
322 private Map<Object,Object> newMap() { 419 private Map<Object,Object> newMap() {
323 return new LinkedHashMap<Object,Object>(); 420 return new LinkedHashMap<Object,Object>();
324 } 421 }
325 422
326 public boolean isSet() { 423 public boolean isSet(LuanState luan) throws LuanException {
327 for( Map.Entry<Object,Object> entry : this ) { 424 for( Map.Entry<Object,Object> entry : iterable(luan) ) {
328 if( !entry.getValue().equals(Boolean.TRUE) ) 425 if( !entry.getValue().equals(Boolean.TRUE) )
329 return false; 426 return false;
330 } 427 }
331 return true; 428 return true;
332 } 429 }
333 430
334 public Set<Object> asSet() { 431 public Set<Object> asSet(LuanState luan) throws LuanException {
335 Set<Object> set = new HashSet<Object>(); 432 Set<Object> set = new HashSet<Object>();
336 for( Map.Entry<Object,Object> entry : this ) { 433 for( Map.Entry<Object,Object> entry : iterable(luan) ) {
337 set.add(entry.getKey()); 434 set.add(entry.getKey());
338 } 435 }
339 return set; 436 return set;
340 } 437 }
341 438
342 public Map<Object,Object> asMap() { 439 public Map<Object,Object> asMap(LuanState luan) throws LuanException {
343 Map<Object,Object> map = newMap(); 440 Map<Object,Object> map = newMap();
344 for( Map.Entry<Object,Object> entry : this ) { 441 for( Map.Entry<Object,Object> entry : iterable(luan) ) {
345 map.put(entry.getKey(),entry.getValue()); 442 map.put(entry.getKey(),entry.getValue());
346 } 443 }
347 return map; 444 return map;
348 } 445 }
349 446