Fix weak tables, improve unit test

This commit is contained in:
James Roseborough
2008-04-11 13:44:39 +00:00
parent 89dd1594b4
commit 79734ab679
5 changed files with 85 additions and 53 deletions

View File

@@ -28,7 +28,6 @@ import org.luaj.vm.LFunction;
import org.luaj.vm.LString; import org.luaj.vm.LString;
import org.luaj.vm.LTable; import org.luaj.vm.LTable;
import org.luaj.vm.LValue; import org.luaj.vm.LValue;
import org.luaj.vm.LWeakTable;
import org.luaj.vm.LuaState; import org.luaj.vm.LuaState;
@@ -186,7 +185,9 @@ public class TableLib extends LFunction {
LTable table = vm.totable(2); LTable table = vm.totable(2);
int pos = (n>=3? vm.tointeger(3): 0); int pos = (n>=3? vm.tointeger(3): 0);
vm.resettop(); vm.resettop();
vm.pushlvalue( table.luaRemovePos( pos ) ); LValue v = table.luaRemovePos(pos);
if ( ! v.isNil() )
vm.pushlvalue( v );
break; break;
} }

View File

@@ -49,8 +49,8 @@ import org.luaj.vm.LuaState;
*/ */
public class LTable extends LValue { public class LTable extends LValue {
private Object[] array; protected Object[] array;
private LValue[] hashKeys; protected LValue[] hashKeys;
private Object[] hashValues; private Object[] hashValues;
private int hashEntries; private int hashEntries;
private LTable m_metatable; private LTable m_metatable;
@@ -70,7 +70,8 @@ public class LTable extends LValue {
* in the range 1 .. narray and nhash non-integer keys. * in the range 1 .. narray and nhash non-integer keys.
*/ */
public LTable( int narray, int nhash ) { public LTable( int narray, int nhash ) {
nhash = Math.max(nhash,MIN_HASH_CAPACITY); if ( nhash > 0 && nhash < MIN_HASH_CAPACITY )
nhash = MIN_HASH_CAPACITY;
array = new Object[narray]; array = new Object[narray];
hashKeys = new LValue[nhash]; hashKeys = new LValue[nhash];
hashValues = new Object[nhash]; hashValues = new Object[nhash];
@@ -205,9 +206,8 @@ public class LTable extends LValue {
} }
/** /**
* Return true if the table contains an entry with the given key, false if * Return true if the table contains an entry with the given key,
* not. Ignores the metatable. * false if not. Ignores the metatable.
*
*/ */
public boolean containsKey( LValue key ) { public boolean containsKey( LValue key ) {
if ( key.isInteger() ) { if ( key.isInteger() ) {
@@ -218,11 +218,14 @@ public class LTable extends LValue {
return null != hashGet(key); return null != hashGet(key);
} }
/** Check if a integer-valued key exists */ /**
* Return true if the table contains an entry with the given integer-valued key,
* false if not. Ignores the metatable.
*/
public boolean containsKey( int key ) { public boolean containsKey( int key ) {
return null != (key>0 && key<=array.length? return (key>0 && key<=array.length?
array[key-1]: array[key-1] != null:
hashGet(LInteger.valueOf(key)) ); (hashKeys.length>0 && hashKeys[hashFindSlot(LInteger.valueOf(key))]!=null));
} }
@@ -244,9 +247,9 @@ public class LTable extends LValue {
private static final int MAX_KEY = 0x3fffffff; private static final int MAX_KEY = 0x3fffffff;
/* /**
** Try to find a boundary in table `t'. A `boundary' is an integer index * Try to find a boundary in table `t'. A `boundary' is an integer index
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). * such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
*/ */
public int luaLength() { public int luaLength() {
int j = array.length; int j = array.length;
@@ -258,10 +261,8 @@ public class LTable extends LValue {
// find `i' and `j' such that i is present and j is not // find `i' and `j' such that i is present and j is not
int i = 0; int i = 0;
while ( containsKey(j) && j < MAX_KEY ) { for ( ++j; containsKey(j) && j < MAX_KEY; j*=2 )
i = j; i = j;
j *= 2;
}
// binary search // binary search
while ( j - i > 1) { while ( j - i > 1) {
@@ -289,7 +290,7 @@ public class LTable extends LValue {
org.luaj.vm.LTable t = (org.luaj.vm.LTable) metatable; org.luaj.vm.LTable t = (org.luaj.vm.LTable) metatable;
LValue m = t.get(TM_MODE); LValue m = t.get(TM_MODE);
if ( "v".equals(m.toJavaString()) ) { if ( "v".equals(m.toJavaString()) ) {
// m_backing = new WeakBacking(m_backing); return new LWeakTable(this);
} }
this.m_metatable = t; this.m_metatable = t;
} }
@@ -435,8 +436,8 @@ public class LTable extends LValue {
} }
private boolean compare(int i, int j, LuaState vm, LValue cmpfunc) { private boolean compare(int i, int j, LuaState vm, LValue cmpfunc) {
LValue a = get(i); LValue a = get(i+1);
LValue b = get(j); LValue b = get(j+1);
if ( a.isNil() || b.isNil() ) if ( a.isNil() || b.isNil() )
return false; return false;
if ( ! cmpfunc.isNil() ) { if ( ! cmpfunc.isNil() ) {
@@ -453,9 +454,9 @@ public class LTable extends LValue {
} }
private void swap(int i, int j) { private void swap(int i, int j) {
LValue a = get(i); LValue a = get(i+1);
put(i, get(j)); put(i+1, get(j+1));
put(j, a); put(j+1, a);
} }
/** /**
@@ -478,7 +479,7 @@ public class LTable extends LValue {
Object a = array[i]; Object a = array[i];
if ( a != null ) { if ( a != null ) {
vm.pushinteger(i+1); vm.pushinteger(i+1);
vm.pushlvalue((LValue)a); vm.pushlvalue(normalizeGet(a));
return true; return true;
} else if ( indexedonly ) { } else if ( indexedonly ) {
vm.pushnil(); vm.pushnil();
@@ -493,7 +494,7 @@ public class LTable extends LValue {
if ( v != null ) { if ( v != null ) {
LValue k = hashKeys[i]; LValue k = hashKeys[i];
vm.pushlvalue(k); vm.pushlvalue(k);
vm.pushlvalue((LValue)v); vm.pushlvalue(normalizeGet(v));
return true; return true;
} }
} }
@@ -508,7 +509,7 @@ public class LTable extends LValue {
// first iteration // first iteration
if ( key.isNil() ) if ( key.isNil() )
return -1; return 0;
// is `key' inside array part? // is `key' inside array part?
if ( key.isInteger() ) { if ( key.isInteger() ) {

View File

@@ -36,6 +36,17 @@ public class LWeakTable extends LTable {
super(narray, nhash); super(narray, nhash);
} }
public LWeakTable(LTable copy) {
super( copy.array.length, copy.hashKeys.length );
for ( int i=0, k=1, n=copy.array.length; i<n; i++, k++ )
this.put( k, copy.get(k) );
for ( int i=0, n=copy.hashKeys.length; i<n; i++ ) {
LValue k = copy.hashKeys[i];
if ( k != null )
this.put( k, copy.get(k) );
}
}
protected LValue normalizeGet(Object val) { protected LValue normalizeGet(Object val) {
if ( val != null ) if ( val != null )
val = ((WeakReference)val).get(); val = ((WeakReference)val).get();
@@ -46,4 +57,14 @@ public class LWeakTable extends LTable {
return val==LNil.NIL? null: new WeakReference(val); return val==LNil.NIL? null: new WeakReference(val);
} }
public boolean next(LuaState vm, LValue key, boolean indexedonly) {
while ( super.next(vm, key, indexedonly) ) {
if ( ! vm.isnil(-1) )
return true;
vm.pop(1);
key = vm.poplvalue();
}
return false;
}
} }

View File

@@ -1,3 +1,11 @@
local t = { "one", "two", "three", a='aaa', b='bbb', c='ccc' }
table.insert(t,'six');
table.insert(t,1,'seven');
table.insert(t,4,'eight');
table.insert(t,7,'nine');
table.insert(t,10,'ten'); print( #t )
-- concat -- concat
print( '-- concat tests' ) print( '-- concat tests' )
function tryconcat(t) function tryconcat(t)
@@ -30,26 +38,26 @@ function eles(t,f)
end end
-- insert, maxn -- insert, maxn
print( '-- insert, maxn tests' ) print( '-- insert, len tests' )
local t = { "one", "two", "three", a='aaa', b='bbb', c='ccc' } local t = { "one", "two", "three", a='aaa', b='bbb', c='ccc' }
print( eles(t) ) print( eles(t), #t )
table.insert(t,'six'); print( eles(t) ) table.insert(t,'six'); print( eles(t), #t )
table.insert(t,1,'seven'); print( eles(t) ) table.insert(t,1,'seven'); print( eles(t), #t )
table.insert(t,4,'eight'); print( eles(t) ) table.insert(t,4,'eight'); print( eles(t), #t )
table.insert(t,7,'nine'); print( eles(t) ) table.insert(t,7,'nine'); print( eles(t), #t )
table.insert(t,10,'ten'); print( eles(t) ) table.insert(t,10,'ten'); print( eles(t), #t )
-- remove -- remove
print( '-- remove tests' ) print( '-- remove tests' )
t = { "one", "two", "three", "four", "five", "six", "seven", [10]="ten", a='aaa', b='bbb', c='ccc' } t = { "one", "two", "three", "four", "five", "six", "seven", [10]="ten", a='aaa', b='bbb', c='ccc' }
print( eles(t) ) print( eles(t), #t )
print( 'table.remove(t)', table.remove(t) ); print( eles(t) ) print( 'table.remove(t)', table.remove(t) ); print( eles(t), #t )
print( 'table.remove(t,1)', table.remove(t,1) ); print( eles(t) ) print( 'table.remove(t,1)', table.remove(t,1) ); print( eles(t), #t )
print( 'table.remove(t,3)', table.remove(t,3) ); print( eles(t) ) print( 'table.remove(t,3)', table.remove(t,3) ); print( eles(t), #t )
print( 'table.remove(t,5)', table.remove(t,5) ); print( eles(t) ) print( 'table.remove(t,5)', table.remove(t,5) ); print( eles(t), #t )
print( 'table.remove(t,10)', table.remove(t,10) ); print( eles(t) ) print( 'table.remove(t,10)', table.remove(t,10) ); print( eles(t), #t )
print( 'table.remove(t,-1)', table.remove(t,-1) ); print( eles(t) ) print( 'table.remove(t,-1)', table.remove(t,-1) ); print( eles(t), #t )
print( 'table.remove(t,-1)', table.remove(t,-1) ) ; print( eles(t) ) print( 'table.remove(t,-1)', table.remove(t,-1) ) ; print( eles(t), #t )
-- sort -- sort
print( '-- sort tests' ) print( '-- sort tests' )

View File

@@ -1,28 +1,29 @@
function newtable(t)
n = setmetatable(t,{__mode="v"})
for k,v in pairs(t) do
n[k] = v
end
return n;
end
-- normalized printing -- normalized printing
function eles(t,f) function eles(t,f)
f = f or pairs f = f or pairs
all = {} all = {}
for k,v in f(t) do for k,v in f(t) do
if type(v) == 'table' then
v = '{'..tostring(v.v)..'}'
end
table.insert( all, "["..tostring(k).."]="..tostring(v) ) table.insert( all, "["..tostring(k).."]="..tostring(v) )
end end
table.sort( all ) table.sort( all )
return tostring(t).."{"..table.concat(all,',').."}" return "{"..table.concat(all,',').."}"
end end
function newtable(t)
return setmetatable(t,{__mode="v"})
end
function new(a)
return {v='_'..tostring(a).."_"}
end
-- basic weak-reference table test -- basic weak-reference table test
local src = "return { 'one', 'two', 'three', 'four', a='aaa', b='bbb', c='ccc', d='ddd'}" local weak = newtable{ new('one'), new('two'), new('three'), new('four'), a=new('aaa'), b=new('bbb'), c=new('ccc'), d=new('ddd') }
local weak = newtable( loadstring(src)() )
local strong = { weak[1], weak[3], a=weak.a, c=weak.c } local strong = { weak[1], weak[3], a=weak.a, c=weak.c }
print( 'before, weak:', eles(weak) ) print( 'before, weak:', eles(weak) )
print( 'before, strong:', eles(strong) ) print( 'before, strong:', eles(strong) )