Mercurial Hosting > luan
changeset 221:ec016471c6eb
make LuanTable an interface
git-svn-id: https://luan-java.googlecode.com/svn/trunk@222 21e917c8-12df-6dd8-5cb6-c86387c605b9
line wrap: on
line diff
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/Luan.java --- a/core/src/luan/Luan.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/Luan.java Thu Jul 17 07:49:26 2014 +0000 @@ -145,5 +145,9 @@ return null; } + public static LuanTable newTable() { + return new LuanTableImpl(); + } + private Luan() {} // never }
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/LuanJavaFunction.java --- a/core/src/luan/LuanJavaFunction.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/LuanJavaFunction.java Thu Jul 17 07:49:26 2014 +0000 @@ -202,7 +202,7 @@ for( int i=0; i<a.length; i++ ) { a[i] = Array.get(obj,i); } - return new LuanTable(new ArrayList<Object>(Arrays.asList(a))); + return new LuanTableImpl(new ArrayList<Object>(Arrays.asList(a))); } }; @@ -369,22 +369,22 @@ if( obj instanceof List ) { @SuppressWarnings("unchecked") List<Object> list = (List<Object>)obj; - return new LuanTable(list); + return new LuanTableImpl(list); } if( obj instanceof Map ) { @SuppressWarnings("unchecked") Map<Object,Object> map = (Map<Object,Object>)obj; - return new LuanTable(map); + return new LuanTableImpl(map); } if( obj instanceof Set ) { @SuppressWarnings("unchecked") Set<Object> set = (Set<Object>)obj; - return new LuanTable(set); + return new LuanTableImpl(set); } Class cls = obj.getClass(); if( cls.isArray() && !cls.getComponentType().isPrimitive() ) { Object[] a = (Object[])obj; - return new LuanTable(Arrays.asList(a)); + return new LuanTableImpl(Arrays.asList(a)); } return obj; } @@ -392,8 +392,8 @@ private static final ArgConverter ARG_MAP = new ArgConverter() { public Object convert(Object obj) { - if( obj instanceof LuanTable ) { - LuanTable t = (LuanTable)obj; + if( obj instanceof LuanTableImpl ) { + LuanTableImpl t = (LuanTableImpl)obj; return t.asMap(); } return obj; @@ -402,8 +402,8 @@ private static final ArgConverter ARG_LIST = new ArgConverter() { public Object convert(Object obj) { - if( obj instanceof LuanTable ) { - LuanTable t = (LuanTable)obj; + if( obj instanceof LuanTableImpl ) { + LuanTableImpl t = (LuanTableImpl)obj; if( t.isList() ) return t.asList(); } @@ -413,8 +413,8 @@ private static final ArgConverter ARG_SET = new ArgConverter() { public Object convert(Object obj) { - if( obj instanceof LuanTable ) { - LuanTable t = (LuanTable)obj; + if( obj instanceof LuanTableImpl ) { + LuanTableImpl t = (LuanTableImpl)obj; if( t.isSet() ) return t.asSet(); } @@ -430,8 +430,8 @@ } public Object convert(Object obj) { - if( obj instanceof LuanTable ) { - LuanTable t = (LuanTable)obj; + if( obj instanceof LuanTableImpl ) { + LuanTableImpl t = (LuanTableImpl)obj; if( t.isList() ) { try { return t.asList().toArray(a);
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/LuanState.java --- a/core/src/luan/LuanState.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/LuanState.java Thu Jul 17 07:49:26 2014 +0000 @@ -19,13 +19,13 @@ final List<StackTraceElement> stackTrace = new ArrayList<StackTraceElement>(); - private LuanTable registry; - private LuanTable global; - private LuanTable metatable; // generic metatable + private LuanTableImpl registry; + private LuanTableImpl global; + private LuanTableImpl metatable; // generic metatable protected LuanState() { - registry = new LuanTable(); - global = new LuanTable(); + registry = new LuanTableImpl(); + global = new LuanTableImpl(); global.put("_G",global); metatable = newMetatable(); } @@ -47,7 +47,7 @@ public final LuanTable registryTable(Object key) { LuanTable tbl = (LuanTable)registry.get(key); if( tbl == null ) { - tbl = new LuanTable(); + tbl = new LuanTableImpl(); registry.put(key,tbl); } return tbl; @@ -68,7 +68,7 @@ } public final Object eval(String cmd) { - return eval(cmd,new LuanTable()); + return eval(cmd,new LuanTableImpl()); } public final Object eval(String cmd,LuanTable env) { @@ -99,8 +99,8 @@ return t==null ? null : t.get(op); } - private static LuanTable newMetatable() { - LuanTable metatable = new LuanTable(); + private static LuanTableImpl newMetatable() { + LuanTableImpl metatable = new LuanTableImpl(); try { metatable.put( "__index", new LuanJavaFunction( LuanState.class.getMethod("__index",LuanState.class,Object.class,Object.class), null
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/LuanTable.java --- a/core/src/luan/LuanTable.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/LuanTable.java Thu Jul 17 07:49:26 2014 +0000 @@ -1,392 +1,21 @@ package luan; -import java.util.Iterator; -import java.util.ListIterator; import java.util.Map; -import java.util.HashMap; import java.util.List; -import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; -import java.util.Set; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.regex.Pattern; -public final class LuanTable implements DeepCloneable<LuanTable>, Iterable<Map.Entry<Object,Object>>, LuanRepr { - private Map<Object,Object> map = null; - private List<Object> list = null; - private LuanTable metatable = null; - - public LuanTable() {} - - public LuanTable(LuanTable tbl) { - if( tbl.map != null ) - this.map = new HashMap<Object,Object>(tbl.map); - if( tbl.list != null ) - this.list = new ArrayList<Object>(tbl.list); - } - - public LuanTable(List<Object> list) { - this.list = list; - this.map = new HashMap<Object,Object>(); - map.put("n",list.size()); - for( int i=0; i<list.size(); i++ ) { - if( list.get(i) == null ) { - listToMap(i); - break; - } - } - } - - public LuanTable(Map<Object,Object> map) { - map.remove(null); - for( Iterator<Object> i=map.values().iterator(); i.hasNext(); ) { - if( i.next() == null ) - i.remove(); - } - this.map = map; - } - - public LuanTable(Set<Object> set) { - map = new HashMap<Object,Object>(); - for( Object obj : set ) { - if( obj != null ) - map.put(obj,Boolean.TRUE); - } - } - - @Override public LuanTable shallowClone() { - return new LuanTable(); - } - - @Override public void deepenClone(LuanTable clone,DeepCloner cloner) { - if( map != null ) { - clone.map = new HashMap<Object,Object>(); - for( Map.Entry<Object,Object> entry : map.entrySet() ) { - clone.map.put( cloner.get(entry.getKey()), cloner.get(entry.getValue()) ); - } - } - if( list != null ) { - clone.list = new ArrayList<Object>(); - for( Object obj : list ) { - clone.list.add( cloner.get(obj) ); - } - } - if( metatable != null ) - clone.metatable = cloner.deepClone(metatable); - } - - public boolean isList() { - return map==null || map.isEmpty(); - } - - public List<Object> asList() { - return list!=null ? list : Collections.emptyList(); - } - - public Map<Object,Object> asMap() { - if( list == null || list.isEmpty() ) - return map!=null ? map : Collections.emptyMap(); - Map<Object,Object> rtn = map!=null ? new HashMap<Object,Object>(map) : new HashMap<Object,Object>(); - for( ListIterator iter = list.listIterator(); iter.hasNext(); ) { - int i = iter.nextIndex(); - rtn.put(i+1,iter.next()); - } - return rtn; - } - - public boolean isSet() { - if( list != null ) { - for( Object obj : list ) { - if( obj!=null && !obj.equals(Boolean.TRUE) ) - return false; - } - } - if( map != null ) { - for( Object obj : map.values() ) { - if( !obj.equals(Boolean.TRUE) ) - return false; - } - } - return true; - } - - public Set<Object> asSet() { - if( list == null || list.isEmpty() ) - return map!=null ? map.keySet() : Collections.emptySet(); - Set<Object> rtn = map!=null ? new HashSet<Object>(map.keySet()) : new HashSet<Object>(); - for( int i=1; i<=list.size(); i++ ) { - rtn.add(i); - } - return rtn; - } - - @Override public String toString() { - return "table: " + Integer.toHexString(hashCode()); - } - - @Override public String repr() { - return repr( Collections.newSetFromMap(new IdentityHashMap<LuanTable,Boolean>()) ); - } - - private String repr(Set<LuanTable> set) { - if( !set.add(this) ) { - return "\"<circular reference>\""; - } - StringBuilder sb = new StringBuilder(); - sb.append('{'); - boolean isFirst = true; - if( list != null ) { - boolean gotNull = false; - for( int i=0; i<list.size(); i++ ) { - Object obj = list.get(i); - if( obj==null ) { - gotNull = true; - } else { - if( isFirst ) { - isFirst = false; - } else { - sb.append(", "); - } - if( gotNull ) - sb.append(i+1).append('='); - sb.append(repr(set,obj)); - } - } - } - if( map != null ) { - for( Map.Entry<Object,Object> entry : map.entrySet() ) { - if( isFirst ) { - isFirst = false; - } else { - sb.append(", "); - } - sb.append(reprKey(set,entry.getKey())).append('=').append(repr(set,entry.getValue())); - } - } - sb.append('}'); - return sb.toString(); - } - - private static final Pattern namePtn = Pattern.compile("[a-zA-Z_][a-zA-Z_0-9]*"); - - private static String reprKey(Set<LuanTable> set,Object obj) { - if( obj instanceof String ) { - String s = (String)obj; - if( namePtn.matcher(s).matches() ) - return s; - } - return "[" + repr(set,obj) + "]"; - } - - private static String repr(Set<LuanTable> set,Object obj) { - if( obj instanceof LuanTable ) { - LuanTable t = (LuanTable)obj; - return t.repr(set); - } else { - String s = Luan.repr(obj); - if( s == null ) - s = "<couldn't repr: " + Luan.stringEncode(Luan.toString(obj)) + ">"; - return s; - } - } - - public Object get(Object key) { - if( list != null ) { - Integer iT = Luan.asInteger(key); - if( iT != null ) { - int i = iT - 1; - if( i>=0 && i<list.size() ) - return list.get(i); - } - } - if( map==null ) - return null; - return map.get(key); - } - - public Object put(Object key,Object val) { - Integer iT = Luan.asInteger(key); - if( iT != null ) { - int i = iT - 1; - if( list != null || i == 0 ) { - if( i == list().size() ) { - if( val != null ) { - list.add(val); - mapToList(); - } - return null; - } else if( i>=0 && i<list.size() ) { - Object old = list.get(i); - list.set(i,val); - if( val == null ) { - listToMap(i); - } - return old; - } - } - } - if( map==null ) { - map = new HashMap<Object,Object>(); - } - if( key instanceof Number && !(key instanceof Double) ) { - Number n = (Number)key; - key = Double.valueOf(n.doubleValue()); - } - if( val == null ) { - return map.remove(key); - } else { - return map.put(key,val); - } - } - - private void mapToList() { - if( map != null ) { - while(true) { - Object v = map.remove(Double.valueOf(list.size()+1)); - if( v == null ) - break; - list.add(v); - } - } - } - - private void listToMap(int from) { - if( list != null ) { - while( list.size() > from ) { - int i = list.size() - 1; - Object v = list.remove(i); - if( v != null ) { - if( map==null ) - map = new HashMap<Object,Object>(); - map.put(i+1,v); - } - } - } - } - - private List<Object> list() { - if( list == null ) { - list = new ArrayList<Object>(); - mapToList(); - } - return list; - } - - public void insert(int pos,Object value) { - if( value==null ) - throw new UnsupportedOperationException(); - list().add(pos-1,value); - mapToList(); - } - - public void add(Object value) { - if( value==null ) - throw new UnsupportedOperationException(); - list().add(value); - mapToList(); - } - - public Object remove(int pos) { - return list().remove(pos-1); - } - - public void sort(Comparator<Object> cmp) { - Collections.sort(list(),cmp); - } - - public int length() { - return list==null ? 0 : list.size(); - } - - public Iterator<Map.Entry<Object,Object>> iterator() { - if( list == null ) { - if( map == null ) - return Collections.<Map.Entry<Object,Object>>emptyList().iterator(); - return map.entrySet().iterator(); - } - if( map == null ) - return listIterator(); - 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 ) { - iter = map.entrySet().iterator(); - isList = false; - b = iter.hasNext(); - } - return b; - } - public Map.Entry<Object,Object> next() { - return iter.next(); - } - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - public Iterator<Map.Entry<Object,Object>> listIterator() { - if( list == null ) - 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); - return new MapEntry(key,iter.next()); - } - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } -/* - public Object[] listToArray() { - return list==null ? new Object[0] : list.toArray(); - } -*/ - public LuanTable subList(int from,int to) { - return new LuanTable(new ArrayList<Object>(list().subList(from-1,to-1))); - } - - public LuanTable getMetatable() { - return metatable; - } - - public void setMetatable(LuanTable metatable) { - this.metatable = metatable; - } - - private static final class MapEntry implements Map.Entry<Object,Object> { - private final Object key; - private final Object value; - - MapEntry(Object key,Object value) { - this.key = key; - this.value = value; - } - - @Override public Object getKey() { - return key; - } - - @Override public Object getValue() { - return value; - } - - @Override public Object setValue(Object value) { - throw new UnsupportedOperationException(); - } - } - - public boolean isEmpty() { - return (list==null || list.isEmpty()) && (map==null || map.isEmpty()); - } +public interface LuanTable extends Iterable<Map.Entry<Object,Object>> { + public List<Object> asList(); + public Map<Object,Object> asMap(); + public Object get(Object key); + public Object put(Object key,Object val); + public void insert(int pos,Object value); + public void add(Object value); + public Object remove(int pos); + public void sort(Comparator<Object> cmp); + public int length(); + public LuanTable subList(int from,int to); + public LuanTable getMetatable(); + public void setMetatable(LuanTable metatable); }
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/LuanTableImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/luan/LuanTableImpl.java Thu Jul 17 07:49:26 2014 +0000 @@ -0,0 +1,390 @@ +package luan; + +import java.util.Iterator; +import java.util.ListIterator; +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Set; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.regex.Pattern; + + +public final class LuanTableImpl implements LuanTable, DeepCloneable<LuanTableImpl>, LuanRepr { + private Map<Object,Object> map = null; + private List<Object> list = null; + private LuanTable metatable = null; + + public LuanTableImpl() {} +/* + public LuanTableImpl(LuanTableImpl tbl) { + if( tbl.map != null ) + this.map = new HashMap<Object,Object>(tbl.map); + if( tbl.list != null ) + this.list = new ArrayList<Object>(tbl.list); + } +*/ + LuanTableImpl(List<Object> list) { + this.list = list; + this.map = new HashMap<Object,Object>(); + map.put("n",list.size()); + for( int i=0; i<list.size(); i++ ) { + if( list.get(i) == null ) { + listToMap(i); + break; + } + } + } + + LuanTableImpl(Map<Object,Object> map) { + map.remove(null); + for( Iterator<Object> i=map.values().iterator(); i.hasNext(); ) { + if( i.next() == null ) + i.remove(); + } + this.map = map; + } + + LuanTableImpl(Set<Object> set) { + map = new HashMap<Object,Object>(); + for( Object obj : set ) { + if( obj != null ) + map.put(obj,Boolean.TRUE); + } + } + + @Override public LuanTableImpl shallowClone() { + return new LuanTableImpl(); + } + + @Override public void deepenClone(LuanTableImpl clone,DeepCloner cloner) { + if( map != null ) { + clone.map = new HashMap<Object,Object>(); + for( Map.Entry<Object,Object> entry : map.entrySet() ) { + clone.map.put( cloner.get(entry.getKey()), cloner.get(entry.getValue()) ); + } + } + if( list != null ) { + clone.list = new ArrayList<Object>(); + for( Object obj : list ) { + clone.list.add( cloner.get(obj) ); + } + } + if( metatable != null ) + clone.metatable = cloner.get(metatable); + } + + public boolean isList() { + return map==null || map.isEmpty(); + } + + @Override public List<Object> asList() { + return list!=null ? list : Collections.emptyList(); + } + + @Override public Map<Object,Object> asMap() { + if( list == null || list.isEmpty() ) + return map!=null ? map : Collections.emptyMap(); + Map<Object,Object> rtn = map!=null ? new HashMap<Object,Object>(map) : new HashMap<Object,Object>(); + for( ListIterator iter = list.listIterator(); iter.hasNext(); ) { + int i = iter.nextIndex(); + rtn.put(i+1,iter.next()); + } + return rtn; + } + + public boolean isSet() { + if( list != null ) { + for( Object obj : list ) { + if( obj!=null && !obj.equals(Boolean.TRUE) ) + return false; + } + } + if( map != null ) { + for( Object obj : map.values() ) { + if( !obj.equals(Boolean.TRUE) ) + return false; + } + } + return true; + } + + public Set<Object> asSet() { + if( list == null || list.isEmpty() ) + return map!=null ? map.keySet() : Collections.emptySet(); + Set<Object> rtn = map!=null ? new HashSet<Object>(map.keySet()) : new HashSet<Object>(); + for( int i=1; i<=list.size(); i++ ) { + rtn.add(i); + } + return rtn; + } + + @Override public String toString() { + return "table: " + Integer.toHexString(hashCode()); + } + + @Override public String repr() { + return repr( Collections.newSetFromMap(new IdentityHashMap<LuanTableImpl,Boolean>()) ); + } + + private String repr(Set<LuanTableImpl> set) { + if( !set.add(this) ) { + return "\"<circular reference>\""; + } + StringBuilder sb = new StringBuilder(); + sb.append('{'); + boolean isFirst = true; + if( list != null ) { + boolean gotNull = false; + for( int i=0; i<list.size(); i++ ) { + Object obj = list.get(i); + if( obj==null ) { + gotNull = true; + } else { + if( isFirst ) { + isFirst = false; + } else { + sb.append(", "); + } + if( gotNull ) + sb.append(i+1).append('='); + sb.append(repr(set,obj)); + } + } + } + if( map != null ) { + for( Map.Entry<Object,Object> entry : map.entrySet() ) { + if( isFirst ) { + isFirst = false; + } else { + sb.append(", "); + } + sb.append(reprKey(set,entry.getKey())).append('=').append(repr(set,entry.getValue())); + } + } + sb.append('}'); + return sb.toString(); + } + + private static final Pattern namePtn = Pattern.compile("[a-zA-Z_][a-zA-Z_0-9]*"); + + private static String reprKey(Set<LuanTableImpl> set,Object obj) { + if( obj instanceof String ) { + String s = (String)obj; + if( namePtn.matcher(s).matches() ) + return s; + } + return "[" + repr(set,obj) + "]"; + } + + private static String repr(Set<LuanTableImpl> set,Object obj) { + if( obj instanceof LuanTableImpl ) { + LuanTableImpl t = (LuanTableImpl)obj; + return t.repr(set); + } else { + String s = Luan.repr(obj); + if( s == null ) + s = "<couldn't repr: " + Luan.stringEncode(Luan.toString(obj)) + ">"; + return s; + } + } + + @Override public Object get(Object key) { + if( list != null ) { + Integer iT = Luan.asInteger(key); + if( iT != null ) { + int i = iT - 1; + if( i>=0 && i<list.size() ) + return list.get(i); + } + } + if( map==null ) + return null; + return map.get(key); + } + + @Override public Object put(Object key,Object val) { + Integer iT = Luan.asInteger(key); + if( iT != null ) { + int i = iT - 1; + if( list != null || i == 0 ) { + if( i == list().size() ) { + if( val != null ) { + list.add(val); + mapToList(); + } + return null; + } else if( i>=0 && i<list.size() ) { + Object old = list.get(i); + list.set(i,val); + if( val == null ) { + listToMap(i); + } + return old; + } + } + } + if( map==null ) { + map = new HashMap<Object,Object>(); + } + if( key instanceof Number && !(key instanceof Double) ) { + Number n = (Number)key; + key = Double.valueOf(n.doubleValue()); + } + if( val == null ) { + return map.remove(key); + } else { + return map.put(key,val); + } + } + + private void mapToList() { + if( map != null ) { + while(true) { + Object v = map.remove(Double.valueOf(list.size()+1)); + if( v == null ) + break; + list.add(v); + } + } + } + + private void listToMap(int from) { + if( list != null ) { + while( list.size() > from ) { + int i = list.size() - 1; + Object v = list.remove(i); + if( v != null ) { + if( map==null ) + map = new HashMap<Object,Object>(); + map.put(i+1,v); + } + } + } + } + + private List<Object> list() { + if( list == null ) { + list = new ArrayList<Object>(); + mapToList(); + } + return list; + } + + @Override public void insert(int pos,Object value) { + if( value==null ) + throw new UnsupportedOperationException(); + list().add(pos-1,value); + mapToList(); + } + + @Override public void add(Object value) { + if( value==null ) + throw new UnsupportedOperationException(); + list().add(value); + mapToList(); + } + + @Override public Object remove(int pos) { + return list().remove(pos-1); + } + + @Override public void sort(Comparator<Object> cmp) { + Collections.sort(list(),cmp); + } + + @Override public int length() { + return list==null ? 0 : list.size(); + } + + @Override public Iterator<Map.Entry<Object,Object>> iterator() { + if( list == null ) { + if( map == null ) + return Collections.<Map.Entry<Object,Object>>emptyList().iterator(); + return map.entrySet().iterator(); + } + if( map == null ) + return listIterator(); + 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 ) { + iter = map.entrySet().iterator(); + isList = false; + b = iter.hasNext(); + } + return b; + } + public Map.Entry<Object,Object> next() { + return iter.next(); + } + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + private Iterator<Map.Entry<Object,Object>> listIterator() { + if( list == null ) + 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); + return new MapEntry(key,iter.next()); + } + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override public LuanTable subList(int from,int to) { + LuanTableImpl tbl = new LuanTableImpl(); + tbl.list = new ArrayList<Object>(list().subList(from-1,to-1)); + return tbl; + } + + @Override public LuanTable getMetatable() { + return metatable; + } + + @Override public void setMetatable(LuanTable metatable) { + this.metatable = metatable; + } + + private static final class MapEntry implements Map.Entry<Object,Object> { + private final Object key; + private final Object value; + + MapEntry(Object key,Object value) { + this.key = key; + this.value = value; + } + + @Override public Object getKey() { + return key; + } + + @Override public Object getValue() { + return value; + } + + @Override public Object setValue(Object value) { + throw new UnsupportedOperationException(); + } + } + + public boolean isEmpty() { + return (list==null || list.isEmpty()) && (map==null || map.isEmpty()); + } +}
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/impl/LuanCompiler.java --- a/core/src/luan/impl/LuanCompiler.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/impl/LuanCompiler.java Thu Jul 17 07:49:26 2014 +0000 @@ -6,6 +6,7 @@ import luan.LuanSource; import luan.LuanElement; import luan.LuanTable; +import luan.Luan; import java.util.Map; @@ -15,7 +16,7 @@ public static LuanFunction compile(LuanState luan,LuanSource src,LuanTable env,boolean allowExpr) throws LuanException { boolean passedEnv = env != null; if( !passedEnv ) - env = new LuanTable(); + env = Luan.newTable(); UpValue.Getter envGetter = new UpValue.ValueGetter(env); LuanParser parser = new LuanParser(src,envGetter); for( Map.Entry<Object,Object> entry : luan.global() ) {
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/impl/TableExpr.java --- a/core/src/luan/impl/TableExpr.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/impl/TableExpr.java Thu Jul 17 07:49:26 2014 +0000 @@ -3,6 +3,7 @@ import luan.LuanException; import luan.LuanTable; import luan.LuanSource; +import luan.Luan; final class TableExpr extends CodeImpl implements Expr { @@ -27,7 +28,7 @@ } @Override public Object eval(LuanStateImpl luan) throws LuanException { - LuanTable table = new LuanTable(); + LuanTable table = Luan.newTable(); for( Field field : fields ) { table.put( field.key.eval(luan), field.value.eval(luan) ); }
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/modules/BasicLuan.java --- a/core/src/luan/modules/BasicLuan.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/modules/BasicLuan.java Thu Jul 17 07:49:26 2014 +0000 @@ -22,7 +22,7 @@ public static final LuanFunction LOADER = new LuanFunction() { @Override public Object call(LuanState luan,Object[] args) { - LuanTable module = new LuanTable(); + LuanTable module = Luan.newTable(); try { module.put( "assert", new LuanJavaFunction(BasicLuan.class.getMethod("assert_",LuanState.class,Object.class,String.class),null) ); add( module, "assert_boolean", LuanState.class, Boolean.TYPE ); @@ -85,8 +85,11 @@ return luan.call(fn); } - private static LuanFunction pairs(final Iterator<Map.Entry<Object,Object>> iter) { + public static LuanFunction pairs(LuanState luan,final LuanTable t) throws LuanException { + Utils.checkNotNull(luan,t,"table"); return new LuanFunction() { + Iterator<Map.Entry<Object,Object>> iter = t.iterator(); + @Override public Object[] call(LuanState luan,Object[] args) { if( !iter.hasNext() ) return LuanFunction.NOTHING; @@ -96,14 +99,20 @@ }; } - public static LuanFunction pairs(LuanState luan,LuanTable t) throws LuanException { + public static LuanFunction ipairs(LuanState luan,final LuanTable t) throws LuanException { Utils.checkNotNull(luan,t,"table"); - return pairs( t.iterator() ); - } + return new LuanFunction() { + List<Object> list = t.asList(); + int i = 0; + final int size = list.size(); - public static LuanFunction ipairs(LuanState luan,LuanTable t) throws LuanException { - Utils.checkNotNull(luan,t,"table"); - return pairs( t.listIterator() ); + @Override public Object[] call(LuanState luan,Object[] args) { + if( i >= size ) + return LuanFunction.NOTHING; + Object val = list.get(i++); + return new Object[]{i,val}; + } + }; } public static LuanTable get_metatable(LuanState luan,Object obj) {
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/modules/BinaryLuan.java --- a/core/src/luan/modules/BinaryLuan.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/modules/BinaryLuan.java Thu Jul 17 07:49:26 2014 +0000 @@ -1,5 +1,6 @@ package luan.modules; +import luan.Luan; import luan.LuanState; import luan.LuanTable; import luan.LuanFunction; @@ -11,7 +12,7 @@ public static final LuanFunction LOADER = new LuanFunction() { @Override public Object call(LuanState luan,Object[] args) { - LuanTable module = new LuanTable(); + LuanTable module = Luan.newTable(); try { add( module, "to_string", new byte[0].getClass() ); } catch(NoSuchMethodException e) {
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/modules/HtmlLuan.java --- a/core/src/luan/modules/HtmlLuan.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/modules/HtmlLuan.java Thu Jul 17 07:49:26 2014 +0000 @@ -1,5 +1,6 @@ package luan.modules; +import luan.Luan; import luan.LuanState; import luan.LuanTable; import luan.LuanFunction; @@ -11,7 +12,7 @@ public static final LuanFunction LOADER = new LuanFunction() { @Override public Object call(LuanState luan,Object[] args) { - LuanTable module = new LuanTable(); + LuanTable module = Luan.newTable(); try { add( module, "encode", String.class ); } catch(NoSuchMethodException e) {
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/modules/IoLuan.java --- a/core/src/luan/modules/IoLuan.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/modules/IoLuan.java Thu Jul 17 07:49:26 2014 +0000 @@ -24,6 +24,7 @@ import java.net.MalformedURLException; import java.util.List; import java.util.ArrayList; +import luan.Luan; import luan.LuanState; import luan.LuanTable; import luan.LuanFunction; @@ -35,12 +36,12 @@ public static final LuanFunction LOADER = new LuanFunction() { @Override public Object call(LuanState luan,Object[] args) { - LuanTable module = new LuanTable(); + LuanTable module = Luan.newTable(); try { add( module, "File", LuanState.class, String.class ); add( module, "read_console_line", String.class ); - LuanTable stdin = new LuanTable(); + LuanTable stdin = Luan.newTable(); stdin.put( "read_text", new LuanJavaFunction( IoLuan.class.getMethod( "stdin_read_text" ), null ) ); @@ -133,7 +134,7 @@ } private static LuanTable writer(LuanWriter luanWriter) { - LuanTable writer = new LuanTable(); + LuanTable writer = Luan.newTable(); try { writer.put( "write", new LuanJavaFunction( LuanWriter.class.getMethod( "write", LuanState.class, new Object[0].getClass() ), luanWriter @@ -149,7 +150,7 @@ public static LuanTable binaryWriter(final OutputStream out) { - LuanTable writer = new LuanTable(); + LuanTable writer = Luan.newTable(); try { writer.put( "write", new LuanJavaFunction( OutputStream.class.getMethod( "write", new byte[0].getClass() ), out @@ -238,7 +239,7 @@ } LuanTable table() { - LuanTable tbl = new LuanTable(); + LuanTable tbl = Luan.newTable(); try { tbl.put( "to_string", new LuanJavaFunction( LuanIn.class.getMethod( "to_string" ), this @@ -358,7 +359,7 @@ File[] files = file.listFiles(); if( files==null ) return null; - LuanTable list = new LuanTable(); + LuanTable list = Luan.newTable(); for( File f : files ) { list.add(new LuanFile(luan,f).table()); }
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/modules/JavaLuan.java --- a/core/src/luan/modules/JavaLuan.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/modules/JavaLuan.java Thu Jul 17 07:49:26 2014 +0000 @@ -29,7 +29,7 @@ public static final LuanFunction LOADER = new LuanFunction() { @Override public Object call(LuanState luan,Object[] args) { - LuanTable module = new LuanTable(); + LuanTable module = Luan.newTable(); try { module.put( "class", new LuanJavaFunction(JavaLuan.class.getMethod("getClass",LuanState.class,String.class),null) ); add( module, "proxy", LuanState.class, Static.class, LuanTable.class, Object.class );
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/modules/MathLuan.java --- a/core/src/luan/modules/MathLuan.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/modules/MathLuan.java Thu Jul 17 07:49:26 2014 +0000 @@ -1,5 +1,6 @@ package luan.modules; +import luan.Luan; import luan.LuanState; import luan.LuanTable; import luan.LuanFunction; @@ -11,7 +12,7 @@ public static final LuanFunction LOADER = new LuanFunction() { @Override public Object call(LuanState luan,Object[] args) { - LuanTable module = new LuanTable(); + LuanTable module = Luan.newTable(); try { add( module, "abs", Double.TYPE ); add( module, "acos", Double.TYPE );
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/modules/PackageLuan.java --- a/core/src/luan/modules/PackageLuan.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/modules/PackageLuan.java Thu Jul 17 07:49:26 2014 +0000 @@ -19,9 +19,9 @@ public static final LuanFunction LOADER = new LuanFunction() { @Override public Object call(LuanState luan,Object[] args) { - LuanTable module = new LuanTable(); + LuanTable module = Luan.newTable(); module.put( "loaded", loaded(luan) ); - module.put( "preload", new LuanTable() ); + module.put( "preload", Luan.newTable() ); module.put( "path", "?.luan;java:luan/modules/?.luan" ); module.put( "jpath", jpath ); try { @@ -70,7 +70,7 @@ String key = "Package.searchers"; LuanTable tbl = (LuanTable)luan.registry().get(key); if( tbl == null ) { - tbl = new LuanTable(); + tbl = Luan.newTable(); tbl.add(preloadSearcher); tbl.add(fileSearcher); tbl.add(javaSearcher);
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/modules/PickleClient.java --- a/core/src/luan/modules/PickleClient.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/modules/PickleClient.java Thu Jul 17 07:49:26 2014 +0000 @@ -64,7 +64,7 @@ } LuanTable table() { - LuanTable tbl = new LuanTable(); + LuanTable tbl = Luan.newTable(); try { tbl.put( "pickle", new LuanJavaFunction( PickleCon.class.getMethod( "pickle", Object.class ), con
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/modules/PickleCon.java --- a/core/src/luan/modules/PickleCon.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/modules/PickleCon.java Thu Jul 17 07:49:26 2014 +0000 @@ -26,7 +26,7 @@ private final DataOutputStream out; private final List<byte[]> binaries = new ArrayList<byte[]>(); String src; - final LuanTable env = new LuanTable(); + final LuanTable env = Luan.newTable(); PickleCon(LuanState luan,DataInputStream in,DataOutputStream out) { this.in = in;
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/modules/StringLuan.java --- a/core/src/luan/modules/StringLuan.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/modules/StringLuan.java Thu Jul 17 07:49:26 2014 +0000 @@ -15,7 +15,7 @@ public static final LuanFunction LOADER = new LuanFunction() { @Override public Object call(LuanState luan,Object[] args) { - LuanTable module = new LuanTable(); + LuanTable module = Luan.newTable(); try { add( module, "to_binary", String.class ); add( module, "to_integers", String.class );
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/modules/TableLuan.java --- a/core/src/luan/modules/TableLuan.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/modules/TableLuan.java Thu Jul 17 07:49:26 2014 +0000 @@ -18,7 +18,7 @@ public static final LuanFunction LOADER = new LuanFunction() { @Override public Object call(LuanState luan,Object[] args) { - LuanTable module = new LuanTable(); + LuanTable module = Luan.newTable(); try { add( module, "concat", LuanState.class, LuanTable.class, String.class, Integer.class, Integer.class ); add( module, "insert", LuanState.class, LuanTable.class, Integer.TYPE, Object.class ); @@ -111,7 +111,20 @@ } public static LuanTable pack(Object... args) { - return new LuanTable(new ArrayList<Object>(Arrays.asList(args))); + LuanTable tbl = Luan.newTable(); + boolean hasNull = false; + for( int i=0; i<args.length; i++ ) { + Object v = args[i]; + if( v==null ) { + hasNull = true; + } else if( !hasNull ) { + tbl.add(v); + } else { + tbl.put(i+1,v); + } + } + tbl.put( "n", args.length ); + return tbl; } public static Object[] unpack(LuanTable tbl,Integer iFrom,Integer iTo) {
diff -r 61afe2a1ce96 -r ec016471c6eb core/src/luan/modules/ThreadLuan.java --- a/core/src/luan/modules/ThreadLuan.java Wed Jul 16 04:59:45 2014 +0000 +++ b/core/src/luan/modules/ThreadLuan.java Thu Jul 17 07:49:26 2014 +0000 @@ -2,6 +2,7 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; +import luan.Luan; import luan.LuanState; import luan.LuanFunction; import luan.LuanTable; @@ -14,7 +15,7 @@ public static final LuanFunction LOADER = new LuanFunction() { @Override public Object call(LuanState luan,Object[] args) { - LuanTable module = new LuanTable(); + LuanTable module = Luan.newTable(); try { add( module, "fork", LuanState.class, LuanFunction.class, new Object[0].getClass() ); } catch(NoSuchMethodException e) {
diff -r 61afe2a1ce96 -r ec016471c6eb dist/luan-core-trunk.jar Binary file dist/luan-core-trunk.jar has changed
diff -r 61afe2a1ce96 -r ec016471c6eb dist/luan-logging-trunk.jar Binary file dist/luan-logging-trunk.jar has changed
diff -r 61afe2a1ce96 -r ec016471c6eb dist/luan-web-trunk.jar Binary file dist/luan-web-trunk.jar has changed
diff -r 61afe2a1ce96 -r ec016471c6eb logging/src/luan/modules/logging/LuanLogger.java --- a/logging/src/luan/modules/logging/LuanLogger.java Wed Jul 16 04:59:45 2014 +0000 +++ b/logging/src/luan/modules/logging/LuanLogger.java Thu Jul 17 07:49:26 2014 +0000 @@ -1,6 +1,7 @@ package luan.modules.logging; import org.apache.log4j.Logger; +import luan.Luan; import luan.LuanState; import luan.LuanException; import luan.LuanTable; @@ -31,7 +32,7 @@ } public LuanTable table() { - LuanTable tbl = new LuanTable(); + LuanTable tbl = Luan.newTable(); try { tbl.put( "error", new LuanJavaFunction( LuanLogger.class.getMethod( "error", LuanState.class, Object.class ), this
diff -r 61afe2a1ce96 -r ec016471c6eb web/src/luan/modules/web/HttpLuan.java --- a/web/src/luan/modules/web/HttpLuan.java Wed Jul 16 04:59:45 2014 +0000 +++ b/web/src/luan/modules/web/HttpLuan.java Thu Jul 17 07:49:26 2014 +0000 @@ -28,7 +28,7 @@ public static final LuanFunction LOADER = new LuanFunction() { @Override public Object call(LuanState luan,Object[] args) { - LuanTable module = new LuanTable(); + LuanTable module = Luan.newTable(); try { addStatic( module, "new_luan_handler", LuanState.class ); } catch(NoSuchMethodException e) { @@ -114,7 +114,7 @@ } private LuanTable requestTable() throws NoSuchMethodException { - LuanTable tbl = new LuanTable(); + LuanTable tbl = Luan.newTable(); tbl.put("java",request); add( tbl, "get_parameter", String.class ); tbl.put( "get_header", new LuanJavaFunction( @@ -137,7 +137,7 @@ } private LuanTable responseTable() throws NoSuchMethodException { - LuanTable tbl = new LuanTable(); + LuanTable tbl = Luan.newTable(); tbl.put("java",response); add( tbl, "send_redirect", String.class ); add( tbl, "send_error", Integer.TYPE, String.class ); @@ -158,7 +158,7 @@ } private LuanTable cookieTable() throws NoSuchMethodException { - LuanTable tbl = new LuanTable(); + LuanTable tbl = Luan.newTable(); tbl.put( "get", new LuanJavaFunction( HttpLuan.class.getMethod("get_cookie",String.class), this ) ); @@ -172,7 +172,7 @@ } private LuanTable sessionTable() throws NoSuchMethodException { - LuanTable tbl = new LuanTable(); + LuanTable tbl = Luan.newTable(); tbl.put( "get_attribute", new LuanJavaFunction( HttpLuan.class.getMethod("get_session_attribute",String.class), this ) );