Fix next()

This commit is contained in:
James Roseborough
2007-11-20 00:10:18 +00:00
parent ad5e776dc9
commit 62a3510272
10 changed files with 217 additions and 74 deletions

View File

@@ -214,7 +214,7 @@ public class BaseLib extends LFunction {
LString s = vm.tolstring(2); LString s = vm.tolstring(2);
int base = 10; int base = 10;
if ( vm.isnumber(3) ) { if ( vm.isnumber(3) ) {
base = vm.tointeger(3); base = vm.tolnumber(3).toJavaInt();
if ( base < 2 || base > 36 ) if ( base < 2 || base > 36 )
vm.error("bad argument #2 to '?' (base out of range)"); vm.error("bad argument #2 to '?' (base out of range)");
} }
@@ -281,9 +281,9 @@ public class BaseLib extends LFunction {
} }
case SELECT: { case SELECT: {
checkargexists(vm,2,Lua.LUA_TNUMBER); checkargexists(vm,2,Lua.LUA_TNUMBER);
int n = vm.gettop(); int n = vm.gettop();
if ( vm.isnumber(2) ) { if ( vm.isnumber(2) ) {
int index = vm.tointeger(2); int index = vm.tolnumber(2).toJavaInt();
if ( index < 0 ) if ( index < 0 )
index += n-1; index += n-1;
if ( index <= 0 ) if ( index <= 0 )
@@ -339,11 +339,11 @@ public class BaseLib extends LFunction {
int i=1,j; int i=1,j;
if ( n >= 3 ) { if ( n >= 3 ) {
checkargtype(vm,3,Lua.LUA_TNUMBER); checkargtype(vm,3,Lua.LUA_TNUMBER);
i = vm.tointeger(3); i = vm.tolnumber(3).toJavaInt();
} }
if ( n >= 4 ) { if ( n >= 4 ) {
checkargtype(vm,4,Lua.LUA_TNUMBER); checkargtype(vm,4,Lua.LUA_TNUMBER);
j = vm.tointeger(4); j = vm.tolnumber(4).toJavaInt();
} else { } else {
j = list.luaLength(); j = list.luaLength();
} }

View File

@@ -636,58 +636,64 @@ public class LTable extends LValue {
} }
/** /**
* Leave nil on top, or index,value pair * Leave key,value pair on top, or nil if at end of list.
* @param vm * @param vm the LuaState to leave the values on
* @param index * @param index index to start search
*/ */
public void next(LuaState vm, LValue index) { public void next(LuaState vm, LValue key ) {
// find place to start looking
int start = nextKey2StartIndex( vm, key );
// look through vector first // look in vector part
int start = index.toJavaInt(); int n = m_vector.length;
if ( start > 0 && start <= m_vector.length ) { if ( start < n ) {
for ( int i=start; i<m_vector.length; i++ ) { for ( int i=start; i<n; i++ ) {
if ( m_vector[i] != LNil.NIL ) { if ( m_vector[i] != LNil.NIL ) {
vm.pushinteger(i+1); vm.pushinteger(i+1);
vm.pushlvalue(m_vector[i]); vm.pushlvalue(m_vector[i]);
return; return;
} }
} }
} start = n;
}
// look up key first // look in hash part
if ( index != LNil.NIL ) { if ( m_hashKeys != null ) {
if ( m_hashEntries != 0 && (start <= 0 || start > m_vector.length) ) { for ( int i=start-n; i<m_hashKeys.length; i++ ) {
for ( int i=0; i<m_hashKeys.length; i++ ) { if ( m_hashKeys[i] != null ) {
if ( index.luaBinCmpUnknown( Lua.OP_EQ, m_hashKeys[i] ) ) { vm.pushlvalue(m_hashKeys[i]);
start = m_vector.length+i+1; vm.pushlvalue(m_hashValues[i]);
break; return;
}
} }
} }
} }
// start looking // nothing found, return nil.
if ( start < m_vector.length ) {
if ( m_arrayEntries != 0 ) {
for ( int i=start; i<m_vector.length; i++ ) {
if ( m_vector[i] != LNil.NIL ) {
vm.pushinteger(i+1);
vm.pushlvalue(m_vector[i]);
return;
}
}
start = m_vector.length;
}
if ( m_hashEntries != 0 ) {
for ( int i=start-m_vector.length; i<m_hashKeys.length; i++ ) {
if ( index.luaBinCmpUnknown( Lua.OP_EQ, m_hashKeys[i] ) ) {
vm.pushlvalue(m_hashKeys[i]);
vm.pushlvalue(m_hashValues[i]);
return;
}
}
}
}
vm.pushnil(); vm.pushnil();
} }
private int nextKey2StartIndex( LuaState vm, LValue key ) {
if ( key == LNil.NIL )
return 0;
int n = m_vector.length;
if ( n > 0 && key.isInteger() ) {
final int index = key.toJavaInt() - 1;
if ( index >= 0 && index < n ) {
if ( m_vector[index] == LNil.NIL )
vm.error( "invalid key to 'next'" );
return index + 1;
}
}
if ( m_hashKeys == null )
vm.error( "invalid key to 'next'" );
int slot = findSlot( key );
if ( m_hashKeys[slot] == null )
vm.error( "invalid key to 'next'" );
return n + slot + 1;
}
} }

View File

@@ -135,7 +135,8 @@ public class DebugLuaState extends LuaState implements DebugRequestListener {
if (exiting) { if (exiting) {
throw new AbortException("aborted by debug client"); throw new AbortException("aborted by debug client");
} }
/*
if (DebugUtils.IS_DEBUG) { if (DebugUtils.IS_DEBUG) {
DebugUtils.println("entered debugHook on pc=" + pc + "...Line: " + getFileLine(cc)); DebugUtils.println("entered debugHook on pc=" + pc + "...Line: " + getFileLine(cc));
for (int j = 0; j <= cc; j++) { for (int j = 0; j <= cc; j++) {
@@ -143,7 +144,7 @@ public class DebugLuaState extends LuaState implements DebugRequestListener {
dumpStack(j); dumpStack(j);
} }
} }
*/
synchronized (this) { synchronized (this) {
while (bSuspendOnStart) { while (bSuspendOnStart) {
try { try {

View File

@@ -78,6 +78,10 @@ public class LuaJTest extends TestCase {
runTest( "metatables" ); runTest( "metatables" );
} }
public void testNext() throws IOException, InterruptedException {
runTest( "next" );
}
public void testPcalls() throws IOException, InterruptedException { public void testPcalls() throws IOException, InterruptedException {
runTest( "pcalls" ); runTest( "pcalls" );
} }
@@ -117,7 +121,7 @@ public class LuaJTest extends TestCase {
public void testUpvalues2() throws IOException, InterruptedException { public void testUpvalues2() throws IOException, InterruptedException {
runTest( "upvalues2" ); runTest( "upvalues2" );
} }
//*/
private void runTest( String testName ) throws IOException, InterruptedException { private void runTest( String testName ) throws IOException, InterruptedException {
// new lua state // new lua state

View File

@@ -1,20 +1,20 @@
-- unit tests for functions in BaseLib.java -- unit tests for functions in BaseLib.java
local ids = {}
local function id(obj)
local v = ids[obj]
if v then
return v
end
table.insert(ids,obj)
ids[obj] = type(obj)..'.'..tostring(#ids)
return ids[obj]
end
-- print
print()
print(11)
print("abc",123,nil,"pqr")
-- error, pcall
print( 'pcall(error)', pcall(error) )
print( 'pcall(error,"msg")', pcall(error,"msg") )
print( 'pcall(error,"msg",1)', pcall(error,"msg",1) )
print( 'pcall(error,"msg",2)', pcall(error,"msg",2) )
local function le(level)
error("msg",level)
end
function ge(level)
error("msg",level)
end
for i = 0,4 do
print( 'pcall(le,i)', i, pcall(le,i) )
print( 'pcall(ge,i)', i, pcall(ge,i) )
end
-- assert -- assert
print( 'assert(true)', assert(true) ) print( 'assert(true)', assert(true) )
@@ -27,7 +27,36 @@ print( 'pcall(assert,nil,"msg")', pcall(assert,nil,"msg") )
print( 'pcall(assert,false,"msg","msg2")', pcall(assert,false,"msg","msg2") ) print( 'pcall(assert,false,"msg","msg2")', pcall(assert,false,"msg","msg2") )
-- collectgarbage (not supported) -- collectgarbage (not supported)
print( 'collectgarbage("count")', id(collectgarbage("count")))
print( 'collectgarbage("collect")', collectgarbage("collect"))
print( 'collectgarbage("count")', id(collectgarbage("count")))
-- dofile (not supported) -- dofile (not supported)
-- ipairs
print( 'pcall(ipairs)', pcall(ipairs) )
print( 'pcall(ipairs,nil)', pcall(ipairs,nil) )
print( 'pcall(ipairs,"a")', pcall(ipairs,"a") )
print( 'pcall(ipairs,1)', pcall(ipairs,1) )
for k,v in ipairs({}) do print('ipairs1',k,v)end
for k,v in ipairs({'one','two'}) do print('ipairs2',k,v)end
for k,v in ipairs({aa='aaa',bb='bbb'}) do print('ipairs3',k,v)end
for k,v in ipairs({aa='aaa',bb='bbb','one','two'}) do print('ipairs4',k,v)end
for k,v in ipairs({[30]='30',[20]='20'}) do print('ipairs5',k,v)end
-- load
-- loadfile
-- loadstring
-- pairs
print( 'pcall(pairs)', pcall(pairs) )
print( 'pcall(pairs,nil)', pcall(pairs,nil) )
print( 'pcall(pairs,"a")', pcall(pairs,"a") )
print( 'pcall(pairs,1)', pcall(pairs,1) )
for k,v in pairs({}) do print('pairs1',k,v)end
for k,v in pairs({'one','two'}) do print('pairs2',k,v)end
for k,v in pairs({aa='aaa',bb='bbb'}) do print('pairs3',k,v)end
for k,v in pairs({aa='aaa',bb='bbb','one','two'}) do print('pairs4',k,v)end
for k,v in pairs({[30]='30',[20]='20'}) do print('pairs5',k,v)end
-- _G -- _G
print( '_G["abc"] (before)', _G["abc"] ) print( '_G["abc"] (before)', _G["abc"] )
@@ -67,16 +96,80 @@ print( 'pcall(setmetatable,nil)', pcall(setmetatable,nil) )
print( 'pcall(setmetatable,"ABC")', pcall(setmetatable,"ABC") ) print( 'pcall(setmetatable,"ABC")', pcall(setmetatable,"ABC") )
print( 'pcall(setmetatable,function() end)', pcall(setmetatable,function() end) ) print( 'pcall(setmetatable,function() end)', pcall(setmetatable,function() end) )
-- ipairs
-- load -- rawget,rawset
-- loadfile local mt = {aa="aaa", bb="bbb"}
-- loadstring mt.__index = mt
-- next mt.__newindex = mt
-- pairs local s = {cc="ccc", dd="ddd", }
-- print local t = {cc="ccc", dd="ddd"}
-- rawget setmetatable(t,mt)
-- rawset print( 'pcall(rawget)', pcall(rawget))
print( 'pcall(rawget,"a")', pcall(rawget,"a"))
print( 'pcall(rawget,s)', pcall(rawget,s))
print( 'pcall(rawget,t)', pcall(rawget,t))
function printtables()
function printtable(name,t)
print( ' '..name, t["aa"], t["bb"], t["cc"], t["dd"], t["ee"], t["ff"], t["gg"] )
print( ' '..name,
rawget(t,"aa"),
rawget(t,"bb"),
rawget(t,"cc"),
rawget(t,"dd"),
rawget(t,"ee"),
rawget(t,"ff"),
rawget(t,"gg") )
end
printtable( 's', s )
printtable( 't', t )
printtable( 'mt', mt )
end
printtables()
print( 'pcall(rawset,s,"aa","www")', id(rawset(s,"aa","www")))
printtables()
print( 'pcall(rawset,s,"cc","xxx")', id(rawset(s,"cc","xxx")))
printtables()
print( 'pcall(rawset,t,"bb","yyy")', id(rawset(t,"aa","yyy")))
printtables()
print( 'pcall(rawset,t,"dd","zzz")', id(rawset(s,"dd","zzz")))
printtables()
printtables()
print( 's["ee"]="ppp"' ); s["ee"]="ppp"
printtables()
print( 's["cc"]="qqq"' ); s["cc"]="qqq"
printtables()
print( 's["bb"]="rrr"' ); t["bb"]="rrr"
printtables()
print( 's["dd"]="sss"' ); t["dd"]="sss"
printtables()
print( 's["gg"]="ttt"' ); mt["gg"]="ttt"
printtables()
-- select -- select
print( 'pcall(select)', pcall(select) )
print( 'select(1,11,22,33,44,55)', select(1,11,22,33,44,55) )
print( 'select(2,11,22,33,44,55)', select(2,11,22,33,44,55) )
print( 'select(3,11,22,33,44,55)', select(3,11,22,33,44,55) )
print( 'select(4,11,22,33,44,55)', select(4,11,22,33,44,55) )
print( 'pcall(select,5,11,22,33,44,55)', pcall(select,5,11,22,33,44,55) )
print( 'pcall(select,6,11,22,33,44,55)', pcall(select,6,11,22,33,44,55) )
print( 'pcall(select,7,11,22,33,44,55)', pcall(select,7,11,22,33,44,55) )
print( 'pcall(select,0,11,22,33,44,55)', pcall(select,0,11,22,33,44,55) )
print( 'pcall(select,-1,11,22,33,44,55)', pcall(select,-1,11,22,33,44,55) )
print( 'pcall(select,-2,11,22,33,44,55)', pcall(select,-2,11,22,33,44,55) )
print( 'pcall(select,-4,11,22,33,44,55)', pcall(select,-4,11,22,33,44,55) )
print( 'pcall(select,-5,11,22,33,44,55)', pcall(select,-5,11,22,33,44,55) )
print( 'pcall(select,-6,11,22,33,44,55)', pcall(select,-6,11,22,33,44,55) )
print( 'pcall(select,1)', pcall(select,1) )
print( 'pcall(select,select)', pcall(select,select) )
print( 'pcall(select,{})', pcall(select,{}) )
print( 'pcall(select,"2",11,22,33)', pcall(select,"2",11,22,33) )
print( 'pcall(select,"abc",11,22,33)', pcall(select,"abc",11,22,33) )
-- tonumber -- tonumber
print( 'pcall(tonumber)', pcall(tostring) ) print( 'pcall(tonumber)', pcall(tostring) )
print( 'pcall(tonumber,nil)', pcall(tonumber,nil) ) print( 'pcall(tonumber,nil)', pcall(tonumber,nil) )
@@ -116,9 +209,9 @@ print( 'pcall(tostring,"abc","def")', pcall(tostring,"abc","def") )
print( 'pcall(tostring,123)', pcall(tostring,123) ) print( 'pcall(tostring,123)', pcall(tostring,123) )
print( 'pcall(tostring,true)', pcall(tostring,true) ) print( 'pcall(tostring,true)', pcall(tostring,true) )
print( 'pcall(tostring,false)', pcall(tostring,false) ) print( 'pcall(tostring,false)', pcall(tostring,false) )
print( 'tostring(tostring):sub(1,10)', tostring(tostring):sub(1,10) ) print( 'tostring(tostring)', id(tostring(tostring)) )
print( 'tostring(function() end)', tostring(function() end):sub(1,10) ) print( 'tostring(function() end)', id(tostring(function() end)) )
print( 'tostring({"one","two",a="aa",b="bb"})', tostring({"one","two",a="aa",b="bb"}):sub(1,7) ) print( 'tostring({"one","two",a="aa",b="bb"})', id(tostring({"one","two",a="aa",b="bb"})) )
-- unpack -- unpack
print( 'pcall(unpack)', pcall(unpack) ); print( 'pcall(unpack)', pcall(unpack) );

Binary file not shown.

23
src/test/res/next.lua Normal file
View File

@@ -0,0 +1,23 @@
-- unit tests for the next() function
function donexts(tag,table,count)
local index = nil
for i = 1,count do
index,value = next(table,index)
print( tag, index, value )
end
print( tag, '--- -1', 'pcall( next, table,-1 )', pcall( next, table,-1 ) )
print( tag, '--- 0', 'pcall( next, table,0 )', pcall( next, table,0 ) )
print( tag, '---"a"', 'pcall( next, table,"a" )', pcall( next, table,"a" ) )
print( tag, '--- 10', 'pcall( next, table, 10 )', pcall( next, table, 10 ) )
end
donexts( 'next1', {}, 2 )
donexts( 'next2', {'one', 'two', 'three' }, 5 )
donexts( 'next3', { aa='aaa', bb='bbb', cc='ccc', [20]='20', [30]='30'}, 7 )
donexts( 'next4', {'one', 'two', 'three', aa='aaa', bb='bbb', cc='ccc', [20]='20', [30]='30'}, 9 )
donexts( 'next5', {'one', 'two', 'three', [-1]='minus-one', [0]='zero' }, 7 )
print( 'pcall(next)', pcall(next) )
print( 'pcall(next,nil)', pcall(next,nil) )
print( 'pcall(next,"a")', pcall(next,"a") )
print( 'pcall(next,1)', pcall(next,1) )

BIN
src/test/res/next.luac Normal file

Binary file not shown.

View File

@@ -34,3 +34,19 @@ print( 'pcall(ct,le,22,33,44)', pcall(ct,le,22,33,44) )
print( "assert(true,'a','b','c')", assert( true, 'a', 'b', 'c' ) ) print( "assert(true,'a','b','c')", assert( true, 'a', 'b', 'c' ) )
print( "pcall(assert,true,'a','b','c')", pcall(assert, true, 'a', 'b', 'c' ) ) print( "pcall(assert,true,'a','b','c')", pcall(assert, true, 'a', 'b', 'c' ) )
print( "pcall(assert,false,'a','b','c')", pcall(assert, false, 'a', 'b', 'c' ) ) print( "pcall(assert,false,'a','b','c')", pcall(assert, false, 'a', 'b', 'c' ) )
-- more error, pcall tests
print( 'pcall(error)', pcall(error) )
print( 'pcall(error,"msg")', pcall(error,"msg") )
print( 'pcall(error,"msg",1)', pcall(error,"msg",1) )
print( 'pcall(error,"msg",2)', pcall(error,"msg",2) )
local function le(level)
error("msg",level)
end
function ge(level)
error("msg",level)
end
for i = 0,4 do
print( 'pcall(le,i)', i, pcall(le,i) )
print( 'pcall(ge,i)', i, pcall(ge,i) )
end

Binary file not shown.