Fix next()
This commit is contained in:
@@ -214,7 +214,7 @@ public class BaseLib extends LFunction {
|
||||
LString s = vm.tolstring(2);
|
||||
int base = 10;
|
||||
if ( vm.isnumber(3) ) {
|
||||
base = vm.tointeger(3);
|
||||
base = vm.tolnumber(3).toJavaInt();
|
||||
if ( base < 2 || base > 36 )
|
||||
vm.error("bad argument #2 to '?' (base out of range)");
|
||||
}
|
||||
@@ -283,7 +283,7 @@ public class BaseLib extends LFunction {
|
||||
checkargexists(vm,2,Lua.LUA_TNUMBER);
|
||||
int n = vm.gettop();
|
||||
if ( vm.isnumber(2) ) {
|
||||
int index = vm.tointeger(2);
|
||||
int index = vm.tolnumber(2).toJavaInt();
|
||||
if ( index < 0 )
|
||||
index += n-1;
|
||||
if ( index <= 0 )
|
||||
@@ -339,11 +339,11 @@ public class BaseLib extends LFunction {
|
||||
int i=1,j;
|
||||
if ( n >= 3 ) {
|
||||
checkargtype(vm,3,Lua.LUA_TNUMBER);
|
||||
i = vm.tointeger(3);
|
||||
i = vm.tolnumber(3).toJavaInt();
|
||||
}
|
||||
if ( n >= 4 ) {
|
||||
checkargtype(vm,4,Lua.LUA_TNUMBER);
|
||||
j = vm.tointeger(4);
|
||||
j = vm.tolnumber(4).toJavaInt();
|
||||
} else {
|
||||
j = list.luaLength();
|
||||
}
|
||||
|
||||
@@ -636,58 +636,64 @@ public class LTable extends LValue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Leave nil on top, or index,value pair
|
||||
* @param vm
|
||||
* @param index
|
||||
* Leave key,value pair on top, or nil if at end of list.
|
||||
* @param vm the LuaState to leave the values on
|
||||
* @param index index to start search
|
||||
*/
|
||||
public void next(LuaState vm, LValue index) {
|
||||
public void next(LuaState vm, LValue key ) {
|
||||
|
||||
// look through vector first
|
||||
int start = index.toJavaInt();
|
||||
if ( start > 0 && start <= m_vector.length ) {
|
||||
for ( int i=start; i<m_vector.length; i++ ) {
|
||||
// find place to start looking
|
||||
int start = nextKey2StartIndex( vm, key );
|
||||
|
||||
// look in vector part
|
||||
int n = m_vector.length;
|
||||
if ( start < n ) {
|
||||
for ( int i=start; i<n; i++ ) {
|
||||
if ( m_vector[i] != LNil.NIL ) {
|
||||
vm.pushinteger(i+1);
|
||||
vm.pushlvalue(m_vector[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
start = n;
|
||||
}
|
||||
|
||||
// look up key first
|
||||
if ( index != LNil.NIL ) {
|
||||
if ( m_hashEntries != 0 && (start <= 0 || start > m_vector.length) ) {
|
||||
for ( int i=0; i<m_hashKeys.length; i++ ) {
|
||||
if ( index.luaBinCmpUnknown( Lua.OP_EQ, m_hashKeys[i] ) ) {
|
||||
start = m_vector.length+i+1;
|
||||
break;
|
||||
}
|
||||
// look in hash part
|
||||
if ( m_hashKeys != null ) {
|
||||
for ( int i=start-n; i<m_hashKeys.length; i++ ) {
|
||||
if ( m_hashKeys[i] != null ) {
|
||||
vm.pushlvalue(m_hashKeys[i]);
|
||||
vm.pushlvalue(m_hashValues[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// start looking
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// nothing found, return nil.
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,6 +136,7 @@ public class DebugLuaState extends LuaState implements DebugRequestListener {
|
||||
throw new AbortException("aborted by debug client");
|
||||
}
|
||||
|
||||
/*
|
||||
if (DebugUtils.IS_DEBUG) {
|
||||
DebugUtils.println("entered debugHook on pc=" + pc + "...Line: " + getFileLine(cc));
|
||||
for (int j = 0; j <= cc; j++) {
|
||||
@@ -143,7 +144,7 @@ public class DebugLuaState extends LuaState implements DebugRequestListener {
|
||||
dumpStack(j);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
synchronized (this) {
|
||||
while (bSuspendOnStart) {
|
||||
try {
|
||||
|
||||
@@ -78,6 +78,10 @@ public class LuaJTest extends TestCase {
|
||||
runTest( "metatables" );
|
||||
}
|
||||
|
||||
public void testNext() throws IOException, InterruptedException {
|
||||
runTest( "next" );
|
||||
}
|
||||
|
||||
public void testPcalls() throws IOException, InterruptedException {
|
||||
runTest( "pcalls" );
|
||||
}
|
||||
@@ -117,7 +121,7 @@ public class LuaJTest extends TestCase {
|
||||
public void testUpvalues2() throws IOException, InterruptedException {
|
||||
runTest( "upvalues2" );
|
||||
}
|
||||
//*/
|
||||
|
||||
private void runTest( String testName ) throws IOException, InterruptedException {
|
||||
|
||||
// new lua state
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
-- 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
|
||||
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") )
|
||||
|
||||
-- collectgarbage (not supported)
|
||||
print( 'collectgarbage("count")', id(collectgarbage("count")))
|
||||
print( 'collectgarbage("collect")', collectgarbage("collect"))
|
||||
print( 'collectgarbage("count")', id(collectgarbage("count")))
|
||||
|
||||
-- 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
|
||||
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,function() end)', pcall(setmetatable,function() end) )
|
||||
|
||||
-- ipairs
|
||||
-- load
|
||||
-- loadfile
|
||||
-- loadstring
|
||||
-- next
|
||||
-- pairs
|
||||
-- print
|
||||
-- rawget
|
||||
-- rawset
|
||||
|
||||
-- rawget,rawset
|
||||
local mt = {aa="aaa", bb="bbb"}
|
||||
mt.__index = mt
|
||||
mt.__newindex = mt
|
||||
local s = {cc="ccc", dd="ddd", }
|
||||
local t = {cc="ccc", dd="ddd"}
|
||||
setmetatable(t,mt)
|
||||
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
|
||||
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
|
||||
print( 'pcall(tonumber)', pcall(tostring) )
|
||||
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,true)', pcall(tostring,true) )
|
||||
print( 'pcall(tostring,false)', pcall(tostring,false) )
|
||||
print( 'tostring(tostring):sub(1,10)', tostring(tostring):sub(1,10) )
|
||||
print( 'tostring(function() end)', tostring(function() end):sub(1,10) )
|
||||
print( 'tostring({"one","two",a="aa",b="bb"})', tostring({"one","two",a="aa",b="bb"}):sub(1,7) )
|
||||
print( 'tostring(tostring)', id(tostring(tostring)) )
|
||||
print( 'tostring(function() end)', id(tostring(function() end)) )
|
||||
print( 'tostring({"one","two",a="aa",b="bb"})', id(tostring({"one","two",a="aa",b="bb"})) )
|
||||
|
||||
-- unpack
|
||||
print( 'pcall(unpack)', pcall(unpack) );
|
||||
|
||||
Binary file not shown.
23
src/test/res/next.lua
Normal file
23
src/test/res/next.lua
Normal 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
BIN
src/test/res/next.luac
Normal file
Binary file not shown.
@@ -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( "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' ) )
|
||||
|
||||
-- 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.
Reference in New Issue
Block a user