https://queue.acm.org/detail.cfm?id=1983083
The main purpose of the stack is to facilitate garbage collection. The GC can find out what Lua objects are currently being manipulated by the C client. The price is that the Lua API can never expose a "Lua object pointer" to C. Many other scripting languages expose such pointers, but then must also expose ways to manage their memory. For example, in Python the user of the API must explicitly increment and decrement reference counts.
Has this changed any?
One trap with the stack is that it baits you into carefully sequencing the operations so that the output of one feeds into the input the the next. Sometimes values are popped far from the places that pushed them... It can be easier to reason about code that liberally copies the temporary values. Keep one stack slot for each "local variable" you want to work with. Then to work on them you copy that slot to the top, call the stack operation, and then write the result back to the appropriate stack slot.
Essentially, favor positive stack indices over negative indices, because the latter are more sensitive to the sequencing of your operations. Also, consider giving names to the stack indices instead of hardcoded numbers.
> Why?
I suspect it's because implementing control mechanisms is much easier when you reify the language's stack. Especially advanced ones such as generators and continuations which require copying the stack into an object and restoring it later. Making that work with the native stack is really hard and many languages don't even try.
It also makes garbage collection precise. Lua values in C variables would be placed in registers or the native stack. In order to trace those values, Lua would require a conservative garbage collector that spills the registers and scans the entire native stack. By managing their own stack, they can avoid doing all that.
> Traditionally, most virtual machines intended for actual execution are stack based, a trend that started with Pascal’s P-machine and continues today with Java’s JVM and Microsoft’s .Net environment. Currently, however, there has been a growing interest in register-based virtual machines (for instance, the planned new virtual machine for Perl 6 (Parrot) will be register based). As far as we know, the virtual machine of Lua 5.0 is the first register-based virtual machine to have a wide use.
The API directly reflected the (previous) internals of the VM, I guess [1].
[1] (pdf) https://www.lua.org/doc/jucs05.pdf
That didn't exist until recently, but now you can use https://github.com/bytecodealliance/wasm-micro-runtime/blob/...
I am not aware of anyone using this yet, but I hope to see that become common in the next few years.
Extism is a plugin framework for WebAssembly:
https://github.com/extism/extism
Postgres and Extism: https://dylibso.com/blog/pg-extism/
Wasm plugins for Zellij: https://zellij.dev/documentation/plugins
Visual Studio Code can run WebAssembly extensions: https://code.visualstudio.com/blogs/2024/05/08/wasm
A project to bring WebAssembly plugins to Godot: https://github.com/ashtonmeuser/godot-wasm
WasmEdge can be embedded in applications: https://wasmedge.org/docs/embed/overview
Wasmer can be embedded in applications: https://blog.wasmer.io/executing-webassembly-in-your-rust-ap...
Wasmtime can be embedded in applications: https://docs.wasmtime.dev/lang.html
It might make sense for building complex plugins, but for simple stuff, Lua still excels, and doesn't require much programming knowledge in many cases.