Mercurial Hosting > luan
diff 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 |
line wrap: on
line diff
--- a/core/src/luan/LuanTable.java Sat May 02 21:12:48 2015 -0600 +++ b/core/src/luan/LuanTable.java Sat May 02 23:41:59 2015 -0600 @@ -15,7 +15,7 @@ import java.util.regex.Pattern; -public final class LuanTable implements Iterable<Map.Entry<Object,Object>>, DeepCloneable<LuanTable> { +public final class LuanTable implements DeepCloneable<LuanTable> { private Map<Object,Object> map = null; private List<Object> list = null; private LuanTable metatable = null; @@ -24,21 +24,34 @@ public LuanTable() {} public LuanTable(List<Object> list) { - this.list = list; - this.map = newMap(); - map.put("n",list.size()); - for( int i=0; i<list.size(); i++ ) { - if( list.get(i) == null ) { - listToMap(i); - break; - } + int n = list.size(); + for( int i=0; i<n; i++ ) { + Object val = list.get(i); + if( val != null ) + rawPut(i+1,val); + } + } + + public LuanTable(Map<Object,Object> map) { + for( Map.Entry<Object,Object> entry : map.entrySet() ) { + Object key = entry.getKey(); + Object value = entry.getValue(); + if( key != null && value != null ) + rawPut(key,value); + } + } + + public LuanTable(Set<Object> set) { + for( Object el : set ) { + if( el != null ) + rawPut(el,Boolean.TRUE); } } public LuanTable(LuanTable tbl) { if( tbl.map != null && !tbl.map.isEmpty() ) this.map = new LinkedHashMap<Object,Object>(tbl.map); - if( tbl.length() > 0 ) + if( tbl.rawLength() > 0 ) this.list = new ArrayList<Object>(tbl.list); this.metatable = tbl.metatable; } @@ -223,13 +236,6 @@ mapToList(); } - public void rawAdd(Object value) { - if( value==null ) - throw new IllegalArgumentException("can't add a nil value"); - list().add(value); - mapToList(); - } - public Object rawRemove(int pos) { return list().remove(pos-1); } @@ -238,11 +244,97 @@ Collections.sort(list(),cmp); } - public int length() { + public int length(LuanState luan) throws LuanException { + Object h = getHandler("__len"); + if( h != null ) { + LuanFunction fn = luan.checkFunction(h); + return (Integer)Luan.first(luan.call(fn,"__len",new Object[]{this})); + } + return rawLength(); + } + + public int rawLength() { return list==null ? 0 : list.size(); } - @Override public Iterator<Map.Entry<Object,Object>> iterator() { + public Iterable<Map.Entry<Object,Object>> iterable(LuanState luan) throws LuanException { + final Iterator<Map.Entry<Object,Object>> iter = iterator(luan); + return new Iterable<Map.Entry<Object,Object>>() { + public Iterator<Map.Entry<Object,Object>> iterator() { + return iter; + } + }; + } + + public Iterator<Map.Entry<Object,Object>> iterator(final LuanState luan) throws LuanException { + if( getHandler("__pairs") == null ) + return rawIterator(); + final LuanFunction fn = pairs(luan); + return new Iterator<Map.Entry<Object,Object>>() { + private Map.Entry<Object,Object> next = getNext(); + + private Map.Entry<Object,Object> getNext() { + try { + Object obj = luan.call(fn); + if( obj==null ) + return null; + Object[] a = (Object[])obj; + if( a.length == 0 ) + return null; + return new AbstractMap.SimpleEntry<Object,Object>(a[0],a[1]); + } catch(LuanException e) { + throw new LuanRuntimeException(e); + } + } + + public boolean hasNext() { + return next != null; + } + + public Map.Entry<Object,Object> next() { + Map.Entry<Object,Object> rtn = next; + next = getNext(); + return rtn; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + public LuanFunction pairs(final LuanState luan) throws LuanException { + Object h = getHandler("__pairs"); + if( h != null ) { + if( h instanceof LuanFunction ) { + Object obj = Luan.first(luan.call((LuanFunction)h,"__pairs",new Object[]{this})); + if( !(obj instanceof LuanFunction) ) + throw luan.exception( "metamethod __pairs should return function but returned " + Luan.type(obj) ); + return (LuanFunction)obj; + } + if( h instanceof LuanMeta ) { + LuanMeta meta = (LuanMeta)h; + return meta.__pairs(luan,this); + } + throw luan.exception( "invalid type of metamethod __pairs: " + Luan.type(h) ); + } + return rawPairs(); + } + + private LuanFunction rawPairs() { + return new LuanFunction() { + final Iterator<Map.Entry<Object,Object>> iter = rawIterator(); + + @Override public Object[] call(LuanState luan,Object[] args) { + if( !iter.hasNext() ) + return LuanFunction.NOTHING; + Map.Entry<Object,Object> entry = iter.next(); + return new Object[]{entry.getKey(),entry.getValue()}; + } + }; + } + + public Iterator<Map.Entry<Object,Object>> rawIterator() { if( list == null ) { if( map == null ) return Collections.<Map.Entry<Object,Object>>emptyList().iterator(); @@ -253,6 +345,7 @@ return new Iterator<Map.Entry<Object,Object>>() { Iterator<Map.Entry<Object,Object>> iter = listIterator(); boolean isList = true; + public boolean hasNext() { boolean b = iter.hasNext(); if( !b && isList ) { @@ -262,9 +355,11 @@ } return b; } + public Map.Entry<Object,Object> next() { return iter.next(); } + public void remove() { throw new UnsupportedOperationException(); } @@ -276,13 +371,16 @@ return Collections.<Map.Entry<Object,Object>>emptyList().iterator(); final ListIterator iter = list.listIterator(); return new Iterator<Map.Entry<Object,Object>>() { + public boolean hasNext() { return iter.hasNext(); } + public Map.Entry<Object,Object> next() { - Double key = Double.valueOf(iter.nextIndex()+1); + Integer key = iter.nextIndex()+1; return new AbstractMap.SimpleEntry<Object,Object>(key,iter.next()); } + public void remove() { throw new UnsupportedOperationException(); } @@ -304,8 +402,7 @@ } public Object getHandler(String op) { - LuanTable t = getMetatable(); - return t==null ? null : t.rawGet(op); + return metatable==null ? null : metatable.rawGet(op); } public boolean hasJava() { @@ -323,25 +420,25 @@ return new LinkedHashMap<Object,Object>(); } - public boolean isSet() { - for( Map.Entry<Object,Object> entry : this ) { + public boolean isSet(LuanState luan) throws LuanException { + for( Map.Entry<Object,Object> entry : iterable(luan) ) { if( !entry.getValue().equals(Boolean.TRUE) ) return false; } return true; } - public Set<Object> asSet() { + public Set<Object> asSet(LuanState luan) throws LuanException { Set<Object> set = new HashSet<Object>(); - for( Map.Entry<Object,Object> entry : this ) { + for( Map.Entry<Object,Object> entry : iterable(luan) ) { set.add(entry.getKey()); } return set; } - public Map<Object,Object> asMap() { + public Map<Object,Object> asMap(LuanState luan) throws LuanException { Map<Object,Object> map = newMap(); - for( Map.Entry<Object,Object> entry : this ) { + for( Map.Entry<Object,Object> entry : iterable(luan) ) { map.put(entry.getKey(),entry.getValue()); } return map;