lua-users home
lua-l archive

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



On 8-Dec-04, at 5:47 PM, Philip Plumlee wrote:

Luists:

Ogle this awesome snip of C++:

       #define TRACE_(x) cout << #x ": " << x << endl

When you use that like this...

       TRACE_(y + z);
       TRACE_(strAnimals);
       TRACE_(__LINE__);

...the program emits this:

       y + z: 12
       strAnimals: Lemmings
       __LINE__:  69

Mighty healthy and easy to write debug statements with, huh? Saves a lot
of keystrokes, huh?

Nice.

Here's how to do it in Lua:

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
    if not name then break end
  end
  return getfenv(level)[k]
end

local function show(_, ...)
  for i = 1, arg.n do arg[i] = tostring(arg[i]) end
  return table.concat(arg, ', ')
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

---- Example, showing all three possibilities

> function foo(a)
>>   local function bar(x, y)
>>     if a then
>>       TRACE_[[a, x+y, author]]
>>     end
>>   end
>>   return bar
>> end
>
> author = "Rici"
> closure = foo "The answer is"
> closure(17, 25)
a, x+y, author: The answer is, 42, Rici

-- Here is why counting levels is necessary (the usual answer is 5,
-- so the search could have started from there)

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

-- Simply setting level to 5 in getvalue results in the following:
> TRACE2_[[s]]
s: Not hidden by TRACE_
> TRACE2_[[(function() return s end)()]]
(function() return s end)(): (function() return s end)()