Lua source code series:
Chapter 5 of “Lua Source Code Appreciation” covers content related to Lua closures.
Contents
Lua Closure Concept
In Lua, binding a set of data to a specific function is called a closure. The bound data are called upvalues, also known as non-local variables (as distinct from local and global variables).
Closure Implementation and Classification
Lua functions differ from C functions in that Lua functions can be dynamically generated during VM runtime - functions can be created within Lua functions. Binding a Lua function prototype with a set of upvalues - binding the Proto structure with UpVal together - is how closures are implemented in Lua.
Lua has two types of closures: Lua closures and C closures. Lua closures are more complex.
- Closures generated during VM runtime: Before a function exits, an index on the data stack is used to map local variables. At this point, the upval is called “open”. When the outer function returns and the data stack space shrinks,
luaF_closeis called to close it, and the previous pointer is redirected to a safe place for storage. - Closures generated from loading external source code (binary or text): Instead of using local variables on the data stack as upvalues, new upvalues are created. Additional note: When Lua loads external code, Lua code is compiled into function prototypes, but Lua’s external calls don’t return function prototypes - instead, they convert the function prototype into a closure.
C closures are simpler than Lua closures. Since C closures don’t reference external upvalues, upvalues are all in a closed state. Just bind the upvalues to the Closure structure. C closures also have a special case with no upvalues, called light C functions. Light functions don’t need the UpVal structure and don’t need GC management.
C Tricks
In Lua source code, the UNUSED() macro is used to avoid compiler unused variable warnings. The source code is:
#define UNUSED(x) ((void)(x))
https://github.com/xiaocang/lua-5.2.2_with_comments/releases/tag/lua_closure_06