lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Rici Lake wrote:

Nice.

Here's how to do it in Lua:

...

Very cool!

Here's a diff that will improve (I think) on the counting levels hack.
It should even allow horrible things like:

    s = "Not hidden by TRACE_"
    TRACE_[[(function() TRACE_"s" return s end)()]]

Although, I'm not sure why anyone would want to do that.

Gordon


*** trace.lua	2004-12-10 01:15:22.000000000 -0500
--- trace2.lua	2004-12-10 01:17:46.000000000 -0500
***************
*** 1,14 ****
! local function getvalue(_, k)
    local level = 1
!   repeat level = level + 1
!   until debug.getlocal(level, 2) == "thisIsWhyIdentifyingCallframesByDepthIsEvil"
!   level = level + 1
    for i = 1, 1e6 do
      local name, val = debug.getlocal(level, i)
      if name == k then return val end
      if not name then break end
    end
-   local func = debug.getinfo(level, "f").func
    for i = 1, 1e6 do
      local name, val = debug.getupvalue(func, i)
      if name == k then return val end
--- 1,14 ----
! local function getvalue(t, k)
!   local func = getmetatable(t).traced_func
    local level = 1
!   repeat
!     level = level + 1
!   until debug.getinfo(level, "f").func == func
    for i = 1, 1e6 do
      local name, val = debug.getlocal(level, i)
      if name == k then return val end
      if not name then break end
    end
    for i = 1, 1e6 do
      local name, val = debug.getupvalue(func, i)
      if name == k then return val end
***************
*** 23,34 ****
  end
  
  function TRACE_(s)
!   local thisIsWhyIdentifyingCallframesByDepthIsEvil = "but there is a hack"
!   local env = setmetatable({}, {__index = getvalue})
    local chunk, msg = loadstring("return "..s)
    if chunk then
      setfenv(chunk, env)
      msg = show(pcall(chunk))
    end
    print(s..": "..msg)
! end
--- 23,34 ----
  end
  
  function TRACE_(s)
!   local tf = debug.getinfo(2, "f").func
!   local env = setmetatable({}, {__index = getvalue, traced_func = tf})
    local chunk, msg = loadstring("return "..s)
    if chunk then
      setfenv(chunk, env)
      msg = show(pcall(chunk))
    end
    print(s..": "..msg)
! end