From 512304475e2ad14ac7ec5640463356a0904d7bde Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Wed, 25 Mar 2009 21:35:20 +0000 Subject: [PATCH] Tests and fixes for debug.setupvalue, getupvalue, setmetatable, and getmetatable --- src/core/org/luaj/lib/DebugLib.java | 50 ++++++++++++++------ src/core/org/luaj/vm/LValue.java | 2 +- src/test/res/debuglib.lua | 71 ++++++++++++++++++++++++++++- 3 files changed, 107 insertions(+), 16 deletions(-) diff --git a/src/core/org/luaj/lib/DebugLib.java b/src/core/org/luaj/lib/DebugLib.java index 749077c0..ebf1404f 100644 --- a/src/core/org/luaj/lib/DebugLib.java +++ b/src/core/org/luaj/lib/DebugLib.java @@ -31,7 +31,7 @@ import org.luaj.vm.LPrototype; import org.luaj.vm.LString; import org.luaj.vm.LTable; import org.luaj.vm.LValue; -import org.luaj.vm.LocVars; +import org.luaj.vm.LuaErrorException; import org.luaj.vm.LuaState; public class DebugLib extends LFunction { @@ -348,15 +348,27 @@ public class DebugLib extends LFunction { private void getmetatable(LuaState vm) { LValue object = vm.topointer(2); vm.resettop(); - vm.pushlvalue( object.luaGetMetatable() ); + LValue mt = object.luaGetMetatable(); + if ( mt != null ) + vm.pushlvalue( object.luaGetMetatable() ); + else + vm.pushnil(); } private void setmetatable(LuaState vm) { LValue object = vm.topointer(2); - LValue table = vm.totable(3); - object.luaSetMetatable(table); - vm.resettop(); - vm.pushlvalue( object ); + try { + if ( ! vm.isnoneornil(3) ) + object.luaSetMetatable(vm.checktable(3)); + else + object.luaSetMetatable(null); + vm.resettop(); + vm.pushboolean(true); + } catch ( LuaErrorException e ) { + vm.resettop(); + vm.pushboolean(false); + vm.pushstring(e.toString()); + } } private void getregistry(LuaState vm) { @@ -364,14 +376,26 @@ public class DebugLib extends LFunction { vm.pushlvalue( new LTable() ); } + private LString findupvalue(LClosure c, int up) { + if ( c.upVals != null && up > 0 && up <= c.upVals.length ) { + if ( c.p.upvalues != null && up <= c.p.upvalues.length ) + return c.p.upvalues[up-1]; + else + return new LString( "."+up+"" ); + } + return null; + } + private void getupvalue(LuaState vm) { LFunction func = vm.checkfunction(2); int up = vm.checkint(3); vm.resettop(); if ( func instanceof LClosure ) { LClosure c = (LClosure) func; - if ( c.upVals != null && up > 0 && up < c.upVals.length ) { - vm.pushlvalue(c.upVals[up].getValue()); + LString name = findupvalue(c, up); + if ( name != null ) { + vm.pushlstring(name); + vm.pushlvalue(c.upVals[up-1].getValue()); return; } } @@ -385,12 +409,10 @@ public class DebugLib extends LFunction { vm.resettop(); if ( func instanceof LClosure ) { LClosure c = (LClosure) func; - if ( c.upVals != null && up > 0 && up < c.upVals.length ) { - c.upVals[up].setValue(value); - if ( c.p.upvalues != null && up < c.p.upvalues.length ) - vm.pushlvalue( c.p.upvalues[up] ); - else - vm.pushstring( "."+up+"" ); + LString name = findupvalue(c, up); + if ( name != null ) { + c.upVals[up-1].setValue(value); + vm.pushlstring(name); return; } } diff --git a/src/core/org/luaj/vm/LValue.java b/src/core/org/luaj/vm/LValue.java index 10237b97..d1c446f6 100644 --- a/src/core/org/luaj/vm/LValue.java +++ b/src/core/org/luaj/vm/LValue.java @@ -181,7 +181,7 @@ public class LValue { * @return this if unchanged, or new LTable if copied using weak table */ public LTable luaSetMetatable(LValue metatable) { - throw new LuaErrorException( "cannot set metatable for "+metatable.luaGetTypeName()); + throw new LuaErrorException( "cannot set metatable for "+this.luaGetTypeName()); } /** Valid for all types: return the int value identifying the type of this value */ diff --git a/src/test/res/debuglib.lua b/src/test/res/debuglib.lua index f541b680..676bd2ac 100644 --- a/src/test/res/debuglib.lua +++ b/src/test/res/debuglib.lua @@ -1,5 +1,5 @@ -local print,tostring,_G = print,tostring,_G +local print,tostring,_G,pcall,ipairs,isnumber = print,tostring,_G,pcall,ipairs,isnumber local e,f,g,h,s print( 'has debug', debug~=nil ) if not debug then error( 'no debug' ) end @@ -49,6 +49,75 @@ do lvl=2,3 end end + +print( '----- debug.getupvalue, debug.setupvalue' ) +local m,n,o = 101,102,103 +f = function(p,q,r) + local p,q,r = 104,105,106 + local g = function(s,t,u) + local v,w,x = 107,108,109 + return function() + return m,n,o,p,q,r,v,w,x + end + end + return g +end +g = f() +h = g() +local callh = function() + local t = {} + for i,v in ipairs( { pcall(h) } ) do + t[i] = tostring(v) + end + return table.concat(t,',') +end +print( 'h', h() ) +local funs = { f, g, h } +local names = { 'f', 'g', 'h' } +for i=1,3 do + local fun,name = funs[i],names[i] + for index=0,10 do + local s1,x1,y1 = pcall( debug.getupvalue, fun, index ) + local s2,x2,y2 = pcall( debug.setupvalue, fun, index, 666000+i*111000+index ) + local s3,x3,y3 = pcall( debug.getupvalue, fun, index ) + print( name..' -> '..i..'-'..index..' '.. + 'get='..tostring(s1)..','..tostring(x1)..','..tostring(y1)..' '.. + 'set='..tostring(s2)..','..tostring(x2)..','..tostring(y2)..' '.. + 'get='..tostring(s3)..','..tostring(x3)..','..tostring(y3)..' '.. + 'tbl='..callh() ) + end +end + +print( '----- debug.setmetatable, debug.getmetatable' ) +local a = {a='bbb'} +local b = {} +local mt = {__index={b='ccc'}} +print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b)) +local s1,x1,y1 = pcall( debug.getmetatable, a ) +local s2,x2,y2 = pcall( debug.setmetatable, a, mt ) +print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b)) +local s3,x3,y3 = pcall( debug.getmetatable, a ) +local s4,x4,y4 = pcall( debug.getmetatable, b ) +local s5,x5,y5 = pcall( debug.setmetatable, a, nil ) +print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b)) +local s6,x6,y6 = pcall( debug.getmetatable, a ) +if not s1 then print( 's1 error', x1 ) end +if not s2 then print( 's2 error', x2 ) end +if not s3 then print( 's3 error', x3 ) end +if not s4 then print( 's4 error', x4 ) end +if not s5 then print( 's5 error', x5 ) end +if not s6 then print( 's6 error', x6 ) end +print( 'get='..tostring(s1)..','..tostring(x1==nil)..','..tostring(y1) ) +print( 'set='..tostring(s2)..','..tostring(x2==a)..','..tostring(y2) ) +print( 'get='..tostring(s3)..','..tostring(x3==mt)..','..tostring(y3) ) +print( 'get='..tostring(s4)..','..tostring(x4==nil)..','..tostring(y4) ) +print( 'set='..tostring(s5)..','..tostring(x5==a)..','..tostring(y5) ) +print( 'get='..tostring(s6)..','..tostring(x6==nil)..','..tostring(y6) ) +print( pcall( debug.getmetatable, 1 ) ) +-- print( pcall( debug.setmetatable, 1, {} ) ) +-- print( pcall( debug.setmetatable, 1, nil ) ) + + --[[ local f = function(a) return 'f:'..tostring(a)..'|'..tostring(b)