3

For quick debugging it is sometimes useful to start a REPL from a script at a certain break-point. I have found out that I can start the Torch REPL at any point by:

require "trepl"
repl()

The only problem with this approach is that the REPL does not see any local variables from the calling chunk. Without being able to inspect locals, the REPL is not really useful as a debugger.

Is it possible to start a REPL which has access to local variables?

Disclaimer: I have found my own (newbie) solution to this problem, but I'm always open for alternatives/suggestions.

bluenote10
  • 23,414
  • 14
  • 122
  • 178

1 Answers1

2

One possible workaround is to use a wrapper, which copies the local variables of the calling scope to the global scope by using debug.getlocal before calling repl():

require "trepl"

function debugRepl(restoreGlobals)
  restoreGlobals = restoreGlobals or false

  -- optionally make a shallow copy of _G
  local oldG = {}
  if restoreGlobals then
    for k, v in pairs(_G) do
      oldG[k] = v
    end
  end

  -- copy upvalues to _G
  local i = 1
  local func = debug.getinfo(2, "f").func
  while true do
    local k, v = debug.getupvalue(func, i)
    if k ~= nil then
      _G[k] = v
    else
      break
    end
    i = i + 1
  end

  -- copy locals to _G
  local i = 1
  while true do
    local k, v = debug.getlocal(2, i)
    if k ~= nil then
      _G[k] = v
    else
      break
    end
    i = i + 1
  end

  repl()

  if restoreGlobals then
    _G = oldG
  end
end

Note (since it is not mentioned in the documentation and only visible from the source): Typing break in the REPL returns execution to the script, while exit (or CTRL+D) terminates the execution completely.

bluenote10
  • 23,414
  • 14
  • 122
  • 178
  • local `oldG` is not seen at the line `_G = oldG` – Egor Skriptunoff Oct 11 '15 at 18:52
  • Why copying locals but not upvalues? – Egor Skriptunoff Oct 11 '15 at 18:54
  • @EgorSkriptunoff: Thanks for the suggestions, I have modified the answer accordingly (thanks to [this answer](http://stackoverflow.com/a/2835433/1804173)). I made a quick test on upvalues and it seems to work fine. – bluenote10 Oct 11 '15 at 21:00
  • Upvalues must be saved BEFORE locals because of name shadowing. – Egor Skriptunoff Oct 11 '15 at 21:33
  • @EgorSkriptunoff: Thanks, I've changed it. To be honest, I don't really see the issue: If a local variable shadows an upvalue it means that the shadowed variable will not be "closed over", so it is not an upvalue in the first place. But then again, I'm just a Lua beginner. – bluenote10 Oct 12 '15 at 14:14
  • 1
    In this code: `local x=1 do local x=x+1 print(x) debugRepl() end` you have local x=2 and upvalue x=1 simultaneously. – Egor Skriptunoff Oct 12 '15 at 14:50