4 ms·
MicroLua for the RP2040 has a nice dsl for the PIO assembly with some special use of methods: https://github.com/MicroLua/MicroLua/blob/main/lib/pico/hardware.p
by mjmas 2y ago
MicroLua for the RP2040 has a nice dsl for the PIO assembly with some special use of methods:
https://github.com/MicroLua/MicroLua/blob/main/lib/pico/hardware.pio.asm.test.lua#L45 https://github.com/MicroLua/MicroLua/blob/main/lib/pico/hard...
function pio_timer(_ENV)
public(start):
set(y, 0)
mov(y, ~y)
wrap_target()
delay:
pull()
mov(x, osr)
loop:
jmp(x_dec, loop)
mov(isr, ~y)
push()
jmp(y_dec, delay)
end
- flykespice 2y agoWas 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...]