lua-users home
lua-l archive

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


It was thus said that the Great Tim Hill once stated:
> For various reasons we need to dynamically move Lua functions (actually
> closures) across lua_State boundaries. This is of course easy using
> dump()/load() pairs, portability of the bytecode is not a problem since
> this is all occurring in-process on a given architecture.

  [ snip ]

> Any ideas anyone???

  First off, I'm using a somewhat bastardized notation from RFC-7049 [1][2]. 
Roughly speaking, the primitive data types are:

	1		unsigned integer
	-1		negative integer
	x0011ff		binary string
	"howdy"		UTF-8 text string
	[ ... ]		array of items
	{ ... }		name/value pairs

On top of that, you can tag the primitive types to extend the semantics:

	_url "http://www.lua.org/";	UTF-8 text string intended as a URL

It's a nice, concise notation and the RFC is quite readable.  Anyway, with
that out of the way, I've been playing around for the past hour or so with
Lua serialization, especially with the problems presented in this thread. 
So, without further ado, let's try this function:

	local x = 1
	local function h() local y = 2 * x print(x) end

As stated, this will have two upvalues, x and _ENV (in that order).  I would
encode this as a tagged (__luafunction) array.  The first element is the
actual code itself, the rest of the elements are upvalues, in order.

	__luafunction [
		x1B4C756153001993... ,		-- function itself
		1,				-- value of x
		__lua "_G"			-- ENV
	]

Here, I'm tagging the string "_G", with __lua.  Yes, the encoding sends a
string, but the tag __lua is used to change the meaning of the string such
that it should be substitued with the standard Lua value of the same name. 
Let's say we have the same function, but with a custom environment:

	{
	  io        = io,
	  select   = select,
	  tostring = tostring,

	  print = function(...)
	    local tab = ""
	    io.stdout:write("DEBUG ")
	    for i = 1 , select('#',...) do
	      io.stdout:write(tab,tostring(select(i,...)))
	      tab = "\t"
	    end
	    io.stdout:write("\n")
	  end
	}

Same function, but the encoding is now:

	__luafunction [
		x1B4C756153001993... ,
		1,
		{
		  "io"       : __lua "io",
		  "select"   : __lua "select",
		  "tostring" : __lua "tostring",
		  "print"    : __luafunction [ x1B4C756153001993... ]
		}
	]

This does presuppose that you can map "function: 0x92b7478" [3] to "select"
and "function: 0x92ba0d0" to "io.open", plus any third party modules that
might be included and referenced.

  Now, this isn't saying you should use CBOR for your encoding, just an idea
of how I might approach this and solve the environment problem with
functions.  You might be able to do a similar thing with your encoding.  

  -spc 

[1]	Concise Binary Object Representation (CBOR)

[2]	I have Lua code (works for Lua 5.1, should work for Lua 5.2, needs
	some work for Lua 5.3) to decode a CBOR [1] encoded message if
	anyone is interested in playing around with it.  I haven't published
	it yet as I'm still working on it.

[3]	On my system, that's what 
		print(select)
	displays.  It might be a different value on your system.  Your
	mileage may vary, etc..