lua-users home
lua-l archive

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


I've been developing a number of libraries for Lua (currently on 5.1w6) for the company I work for (this unfortunately means I can't go into too much detail about them or their uses).

My current main project is a glue code system for allowing Lua scripts to access C variables and functions. Rather than taking the approach to tolua, etc. of directly binding these elements into the Lua namespace, it instead takes a more dynamic object oriented approach.

Proxy objects (tables at their core) intercept attempts to get and set values, look up indices, look up structure/union members and call functions. These appear to the user to be native Lua data types, but instead apply operations to the underlying C equivalent. These proxies are generated on the fly through the use of the __index metamethod.

Unfortunately, I've had to add some metamethods to give them the truly native feel:

__type: Overrides the return value of the Lua function type().
__set: Overrides an attempt to set the value of a Lua value. This is used to make assignment set the value of the underlying C value, rather than replacing the proxy object with the new value. See below for some caveats. __tonumber: Overrides an attempt to convert a Lua value to a number. This is invoked by the C function lua_tonumber(), among other methods. This, along with some modifications to the VM arithmetic operations, allows proxies to be used in mathematical operations as though they were native Lua numbers. __tostring: Overrides an attempt to convert a Lua value to a number. This is invoked by the C function lua_tostring(), among other methods. This allows proxies to be used as though they were native Lua strings. __ueq: Untype checked equals comparison. The normal comparison metamethods do not allow mixed types, preventing numbers from being compared against proxies. This metamethod is invoked when an attempt is made to compare different types.
__ult: Untype checked less than comparison.
__ule: Untype checked less than or equals comparison.
__not: Overrides the not operator. A proxy is really a table, meaning that "not proxy" will always return false. This allows the result to be dependent on the underlying value of the proxy.

Can anybody suggest any ways of providing similar functionality that appears seamless to the end user without having to make these modifications?

There are a couple of troubling issues:

Occasionally, intermittent errors such as "attempt to compare number with boolean" occur. I'm currently putting these down to subtle stack corruption issues, but they squirm away from beneath me when I try to instrument my code. Does anyone have any hints for debugging such issues?

Locals and the __set metamethod - essentially, for every VM cycle, the interpreter has to check whether RA represents a local. If it does, then it will check if the __set metamethod needs to be used. If this check is not done, then everything breaks horribly because the VM attempts to reuse a register and mistakenly triggers the __set metamethod. Currently, I'm walking through the call info stack to determine which registers are locals and which aren't at the start of each cycle, but this is horribly inefficient. I've tried adding a second stack of flags which indicates which registers are locals and which aren't, and this is maintained when the stack is resized, when a Lua function is called, when a Lua function returns, and when a Lua function tail returns. However, this doesn't work - the flags do not mirror the results of the call info stack walk. I suspect this may be related to upvalues and other similar issues. Can anybody shed any light on this issue?

Personally, I don't like having to have made these changes - they make upgrading to new versions of Lua more difficult and slow Lua down - but needs must.

Any assistance people can provide to help me remove my custom metamethods and restore the performance and reliability of the VM would be appreciated. If you need any clarifications, don't hesitate to ask, I'm well aware that I can blabber on a bit :)