And here is a repository with a compiler backend to generate LuaJIT bytecode and other useful tools: https://github.com/rochus-keller/ljtools/
The reason why I switched from generating Lua source code to LuaJIT bytecode in 2019 was mostly the higher flexibility. I could better avoid operations not yet supported by the tracer, and some language features of Oberon+ didn't match well to Lua. And adding line information for debugging was much easier. And it was a fun project and the bytecode was well documented. It's certainly also a bit faster, but I haven't done specific measurements.
My goals are:
Deep copy value passing semantics by default (with outs for hotpath and some optimization).
Persistence by default using SQLite. (Again, opt out for hot paths).
Lua tables, but callable. Also every object is a continuation. Optimizations for js are float64 arrays with the 0 index holding some meta stuff - but semantically just objects and messages.
No variables, just fields.
Fields can be thought of as canned message responses. Fallthrough is “call”.