| I dont really disagree with the main premise of the article, which is that WASM is not really a stack language, but this part just gave me pause: > In textual Wasm, for example, they are instead represented in a LISP-like notation – not any less or more efficient The Text format, at least when it comes to instructions, it 1 to 1 with the binary format. The LISP-like syntax is mainly just syntax sugar[1]. ‘(’ plaininstr instrs ‘)’ ≡ instrs plaininstr
So (in theory, as far as I understand it) you can just do `(local.get 2 local.get 0 local.get 1)` to mean `local.get 0 local.get 1 local.get 2`, and it works for (almost) any instruction.Unfortunately, in my limited testing, tools like `wat2wasm` and Binaryen's `wasm-as` don't seem to adhere to (my perhaps faulty understanding of) the spec, and demand all instructions in a folded block be folded and have the "correct" amount of arguments, which makes Binaryen do weird things like (return
(tuple.make ;; Binaryen only pseudoinstruction
(local.get 0) ;; or w/e expression
(local.get 1) ;; or w/e expression
)
)
when this is perfectly valid local.get 0
local.get 1
return
tl;dr: the LISP syntax is just syntax sugar. The textual format is as "stack-like" as the binary format.Edit: An example that is easily done with the stack syntax and not with lisp syntax is the following: call function_that_returns_multivalue
local.set 2 ;; last return
local.set 1 ;;
local.set 0 ;; first return
In LISP syntax this would be (local.set 0
(local.set 1
(local.set 2
(call function_that_returns_multivalue
( ;; whatever input paramters
)))))
I have not yet tried this with Binaryen but I doubt it flies.[1]: https://webassembly.github.io/spec/core/text/instructions.ht... |
https://raw.githubusercontent.com/soegaard/webracket/refs/he...
As a small example, here is a definition of `$car` which extracts the first value from a pair.