title: change/update value of a local variable (Lua upvalue)
body: <p>I've written a script to hot-reload already <code>require</code>ed modules. It work s only partially however...</p>
  
  <p>My approach to this task is quite simple. I changed Lua's <code>require</code> function so that it remembers modules that it loaded together with a timestamp and its file path. Then I use a shell script to observe the modification time of those files and re-require them if they changed. I simply <code>dofile()</code> and if no errors happen, I take the return value and (re-)assign it at <code>package.loaded[&lt;module&gt;]</code>. So far so good.</p>
  
  <p>All of this works perfect when I use global variables, e.g. <code>foo = require "foobar"</code>, but when I use local assignments, like <code>local foo = require "foobar"</code>, my hotswapper failes (partially)!</p>
  
  <p>It seems that the package gets swapped out like intended, however the local variable (from the assignment above) still holds an old reference or the old value that it got when require was called the first time.</p>
  
  <p>My idea was to use Lua's <code>debug.getlocal</code> and <code>debug.setlocal</code> functions to find all local variables (upvalues in stack) and update their values/references.</p>
  
  <p>BUT I get an error that the upvalue I want to change is "out of range"... Could somebody help me please? What should I do or how could I work around this?</p>
  
  <p><a href="https://gist.github.com/jack0088/f5ec80010ca25de941f471bb42711996" rel="nofollow noreferrer">The complete code is over at Gist</a>, the important/relevant snippets however are...</p>
  
  <ol>
  <li>the function <code>local_upvalues()</code> at line 27, which collects all available upvalues</li>
  </ol>
  
  <pre class="lang-lua prettyprint-override"><code>local function local_upvalues()
      local upvalues = {}
      local failures = 0
      local thread = 0
      while true do
          thread = thread + 1
          local index = 0
          while true do
              index = index + 1
              local success, name, value = pcall(debug.getlocal, thread, index)
              if success and name ~= nil then
                  table.insert(upvalues, {
                      name = name,
                      value = value,
                      thread = thread,
                      index = index
                  })
              else
                  if index == 1 then failures = failures + 1 end
                  break
              end
          end
          if failures &gt; 1 then break end
      end
      return upvalues
  end
  </code></pre>
  
  <ol start="2">
  <li>and the <code>debug.setlocal()</code> at line 89, which tries to update the upvalue that holds the absolete module reference</li>
  </ol>
  
  <pre class="lang-lua prettyprint-override"><code>        -- update module references of local upvalues
          for count, upvalue in ipairs(local_upvalues()) do
              if upvalue.value == package.loaded[resource] then
                  -- print(upvalue.name, "updated from", upvalue.value, "to", message)
                  table.foreach(debug.getinfo(1), print)
                  print(upvalue.name, upvalue.thread, upvalue.index)
                  debug.setlocal(upvalue.thread, upvalue.index, message)
              end
          end
          package.loaded[resource] = message -- update the absolete module
  </code></pre>