lua-users home
lua-l archive

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


  I have the following code:

	local a = 3

	function foo(x)
	  local y = 4 * x + a
	  print(y)
	  return y
	end

	f = io.open("blob","wb")
	x = string.dump(foo)
	f:write(x)
	f:close()

	info = debug.getinfo(foo,"u")
	for i = 1 , info.nups do
	  name,value = debug.getupvalue(foo,i)
	  print(i,name,value)
	end

  I run it.  I now have a file of binary sludge that represents the
function foo(), and the output is:

	1       a       3
	2       _ENV    table: 0x9af23c0

  Okay.  No guarentee that the first upvalue is _ENV.  That shouldn't be a
problem, right?  Anyway, here's the second script I have.

	f = io.open("blob","rb")
	d = f:read("*a")
	f:close()
	
	bar = load(d)
	
	info = debug.getinfo(bar,"u")
	for i = 1 , info.nups do
	  name,value = debug.getupvalue(bar,i)
	  print(i,name,value)
	end

  And when I run it, I get:

	1	a       table: 0x9b4b3c0
	2	_ENV    nil

  Um ... to me, this looks like a bug.  The *names* are in the right order,
but the *values* appear to have been swapped.  Or rather, load() just jammed
_ENV as the first upvalue, original order be damned!  The documentation for
string.dump() says:

	Returns a string containing a binary representation (a binary chunk)
	of the given function, so that a later load on this string returns a
	copy of the function (but with new upvalues). If strip is a true
	value, the binary representation is created without debug
	information about the function (local variable names, lines, etc.).

	Functions with upvalues have only their number of upvalues saved. When
	(re)loaded, those upvalues receive fresh instances containing nil. (You can
	use the debug library to serialize and reload the upvalues of a function in
	a way adequate to your needs.) 

  Well, first off, this is wrong---all but the first upvalue are nil.  And if
you receive stripped code, you don't even get the names!  [1]  Okay, so it
seems I have to shuffle things around.

	_,v = debug.getupvalue(bar,1)
	debug.setupvalue(bar,1,3)
	debug.setupvalue(bar,2,v)
	bar(3)

  And now it works.

  Also, while "you can use the debug library to serialize and reload the
upvalues of a function in a way adequate to your needs" is true, to a
degree, as mentioned elsewhere [2] it's not always that easy.

  -spc (Why yes, I'm trying to serialize Lua functions, silly me)

[1]	In playing around with this, it seems that sometimes _ENV is the
	first upvalue, sometimes the last.  Fun times.

[2]	http://lua-users.org/lists/lua-l/2015-03/msg00180.html