4 ms·
Was that really achieved with vanilla Lua or MicroLua has some language extensions?
by flykespice 2y ago
Was that really achieved with vanilla Lua or MicroLua has some language extensions?
- SyrupThinker 2y agoWhile I can't speak for MicroLua, this can indeed be accomplished with vanilla Lua. There are two things in play here: First, the _ENV variable here is special. It is implicitly used to lookup any identifier that has no visible binding, locally or in the surrounding scopes. Thus a script just containing print("Hello world") is really _ENV.print("Hello world"). Usually _ENV is just implicitly defined to be the global environment (available as _G), but it can be overridden within a lexical scope to a custom value. Second, the jump labels just make use of the alternate function call syntax of object:method(args), which is equivalent to object.method(object, args). The whitespace is non-significant, which allows it to be written like that. In combination with metatables you can use _ENV to track variable reads, calls etc. within a function, which you can (abuse) to create DSLs. You can get an idea of whats possible by just tracking what we can intercept with _ENV. Adding the following code after the pio_timer function, and running the script with Lua 5.4, already gives us quite a bit for just the first three lines of the function. local loggerMetatable = {} function loggerMetatable:__bnot() print("Called bnot on " .. rawget(self, "name")) end function loggerMetatable:__call(...) local name = rawget(self, "name") print("Invoked " .. name .. " with " .. #table.pack(...) .. " args") -- Return another logger table to visualize variable interactions return setmetatable({ name = name .. "(...)" }, loggerMetatable) end function loggerMetatable:__index(key) local name = rawget(self, "name") print("Accessed key " .. key .. " on " .. name) -- Return another logger table to visualize variable interactions return setmetatable({ name = name .. "." .. key }, loggerMetatable) end local pio_env = setmetatable({ name = "_ENV" }, loggerMetatable) pio_timer(pio_env) -- Output: Accessed key public on _ENV Accessed key start on _ENV Invoked _ENV.public with 1 args Accessed key set on _ENV.public(...) Accessed key y on _ENV Invoked _ENV.public(...).set with 3 args Accessed key mov on _ENV Accessed key y on _ENV Accessed key y on _ENV Called bnot on _ENV.y Invoked _ENV.mov with 1 args [...snip...]