diff --git a/src/core/org/luaj/lib/BaseLib.java b/src/core/org/luaj/lib/BaseLib.java index e45aa7ec..a43a1306 100644 --- a/src/core/org/luaj/lib/BaseLib.java +++ b/src/core/org/luaj/lib/BaseLib.java @@ -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)"); } @@ -281,9 +281,9 @@ public class BaseLib extends LFunction { } case SELECT: { checkargexists(vm,2,Lua.LUA_TNUMBER); - int n = vm.gettop(); + 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(); } diff --git a/src/core/org/luaj/vm/LTable.java b/src/core/org/luaj/vm/LTable.java index a24c4061..6116390e 100644 --- a/src/core/org/luaj/vm/LTable.java +++ b/src/core/org/luaj/vm/LTable.java @@ -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 ) { + + // find place to start looking + int start = nextKey2StartIndex( vm, key ); - // look through vector first - int start = index.toJavaInt(); - if ( start > 0 && start <= m_vector.length ) { - for ( int i=start; i m_vector.length) ) { - for ( int i=0; i 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; + } } diff --git a/src/debug/org/luaj/debug/DebugLuaState.java b/src/debug/org/luaj/debug/DebugLuaState.java index 0888b99c..1f536362 100644 --- a/src/debug/org/luaj/debug/DebugLuaState.java +++ b/src/debug/org/luaj/debug/DebugLuaState.java @@ -135,7 +135,8 @@ public class DebugLuaState extends LuaState implements DebugRequestListener { if (exiting) { 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 { diff --git a/src/test/java/org/luaj/vm/LuaJTest.java b/src/test/java/org/luaj/vm/LuaJTest.java index f656c0eb..eda119dd 100644 --- a/src/test/java/org/luaj/vm/LuaJTest.java +++ b/src/test/java/org/luaj/vm/LuaJTest.java @@ -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 diff --git a/src/test/res/baselib.lua b/src/test/res/baselib.lua index 1abf58d9..155eecce 100644 --- a/src/test/res/baselib.lua +++ b/src/test/res/baselib.lua @@ -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) ); diff --git a/src/test/res/baselib.luac b/src/test/res/baselib.luac index 08d29159..2ad89cde 100644 Binary files a/src/test/res/baselib.luac and b/src/test/res/baselib.luac differ diff --git a/src/test/res/next.lua b/src/test/res/next.lua new file mode 100644 index 00000000..36de2f0b --- /dev/null +++ b/src/test/res/next.lua @@ -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) ) + diff --git a/src/test/res/next.luac b/src/test/res/next.luac new file mode 100644 index 00000000..2bb95ed9 Binary files /dev/null and b/src/test/res/next.luac differ diff --git a/src/test/res/pcalls.lua b/src/test/res/pcalls.lua index 12aa0385..066a3ee8 100644 --- a/src/test/res/pcalls.lua +++ b/src/test/res/pcalls.lua @@ -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 diff --git a/src/test/res/pcalls.luac b/src/test/res/pcalls.luac index 4063726f..fc04bd0d 100644 Binary files a/src/test/res/pcalls.luac and b/src/test/res/pcalls.luac differ