Multi-Value All the Wasm
hacks.mozilla.org
hacks.mozilla.org
I kid, sort of. Greenspun and all that.
(Common Lisp has support for multiple values built in. They’re not a “data structure” like a tuple, but rather an extension to data flow and control. Returning a tuple vs returning multiple values are different things, especially when the consumer of the values-produced only actually uses a single value, as is usually the case with e.g. multiple-value-returning functions like GETHASH or FLOOR. FLOOR returns the quotient of floor(x/y), as well as the remainder as a second value. Most of the time you don’t need the second value, and there’s no need to “opt-out”.)
It's not really Forth because in WASM, each block of code needs to have a statically determined stack effect. I wonder if there might be a nice Forth-like syntax for WASM, though?
Check out the section of the docs labeled "The stack": https://docs.factorcode.org/content/article-handbook-languag...
Note that, in particular, there is full support for stack-effect declarations and that there is a static static-effect checker.
And also Python, Go, Rust, Haskell...
- https://github.com/WebAssembly/gc
- https://github.com/WebAssembly/reference-types
- https://github.com/WebAssembly/funclets
As for the eval thing, you surely can compile and execute code on the fly. Such features would be enabled by the aforementioned proposals, but should be possible today as well (through shared memory).
https://github.com/appcypher/awesome-wasm-langs/blob/master/...
No need to get everything served on a plate.
Yes some have buggy implementations, others could do better, yet they exist.
I rather have a half working bicycle that takes me to town than none at all.
A garbage collector that breaks down on circular references is crazy town for real work. Like there's even AI Lab Koan about that specifically. http://catb.org/jargon/html/koans.html
A better example would be a bicycle without the front wheel. Yeah, if you're real good and real careful you can probably treat it as a unicycle and get to where you're going, but you'd be real pissed if someone sold it to you as a working bicycle, no?
PNaCL also did not have direct GC support, yet it got released with working OCaml support.
Enjoying moving goalposts?
Like "technically works enough for a demo" isn't what I'd call full support.
Yes there are bugs in some implementations and others could have been better done, it happens.
Discussing technicalities of who is using what in production is moving goalposts.
Not a big fan of having lost PNaCL in favour of WebAssembly craziness, but that is what we have to work with, GC might come in 5 years time or even never, who knows.
What I know is that despite the flaws, many developers are eager to implement something with what we have now and kudos to them for trying it out.
“They did not know it was impossible so they did it” ― Mark Twain
Also, I looked into it. PNaCl couldn't run OCaml, only NaCl. PNaCl (and wasm) doesn't really let you scan stacks, but NaCl does, so they had to drop a real GC with the semantics you'd expect on the transition to PNaCl.
"They did know it was impossible, so they didn't bother" ~ monocasa
And once again, explaining why your examples aren't valid and refuting them isn't "moving goalposts".
There are plenty of leaking object graphs with circular references implementations in native CPUs, and yet people do use them, starting with C++ standard library collection types or Objective-C ARC.
So your point on refuting whatever I present instead of appreciating the work of the implementations that actually work is kind of moving goalposts.
Because apparently people bother with native CPU implementations, even with those bugs, so why should WebAssembly be any different?!?
You don't want to bother, fine go watch tv, play football, whatever is your fancy.
Me, I will be supporting anyone that with the WebAssembly we get to play with, decides to implement their favourite language.
https://docs.assemblyscript.org/details/runtime#collecting-g...
https://docs.microsoft.com/en-us/aspnet/core/blazor/hosting-...
https://tinygo.org/lang-support/
Like they say back home "Those that don't have dogs hunt with cats".
For example, the CL integer division functions (it has each of floor, truncate, and round) all return the remainder as a second value, but you can ignore that fact if all you wanted was division:
(floor 5 3) -> 1 ; 2
(let ((x (floor 5 3)) x) -> 1
(setf (values x y) (floor 5 3)) (list x y) -> (1 2)My only point here is, I guess, that a thunk (0 argument function) acts a similar way. If we had need to call two instructions (or increase bitwidth) this might suffice:
def floor(n, d = 1)
[-> { n.div(d) }, -> { n.modulo(d) }]
end
p *floor(10.3)
#<Proc:0x0000558aeacdbc00@s.rb:4 (lambda)>
#<Proc:0x0000558aeacdbbd8@s.rb:4 (lambda)>
p floor(10.3).first.call
# 10
p *floor(10.3).map(&:call)
# 10
# 0.3000000000000007There are certainly arguments for why this might be a bad idea (if your the sort of person who likes rich type systems, you're unlikely to like this), but there is no way to do this in WASM efficiently, while there is for pretty much all real machines.
FWIW, I'm not sure about CLISP; I haven't used it for almost 20 years. Sbcl and ccl will both omit the calculation of the modulo when it is not needed. The ergonomics of a thunk or a tuple are different.
Quick question: Is multivalue return supported in LLVM? Or said in other way ...code compiled from Rust or C/C++ will output Wasm with multivalue returns? Or only written-by-hand WebAssembly can take advantage of this at the moment?
EDIT: after reading the article more thoroughly: LLVM doesn't support multivalue returns in Wasm yet. They are using Walrus to do wasm to wasm transformation from the return metadata info they have in wasm-bindgen (Rust).
[1] https://hacks.mozilla.org/2019/11/announcing-the-bytecode-al...
It can also embed the compiled code into the WebAssembly module, so that the same module can directly run the precompiled code (when using WAVM) or be executed as a standard module by another runtime.
Rust will be able to benefit immediately once LLVM has multivalue function support since they use their own ABI internally. But C, C++, and Rust extern functions will not be able to benefit until we additionally define a new C ABI that takes advantage of multivalue returns.
It's also worth noting that multivalue blocks only bring a code size win of a couple percent on real wasm modules, so those are much lower priority.
WebAssembly features are all different in how difficult they are to add to the specification, engines, and tools. Multivalue is unique in that it is trivial for the spec and for engines, but is extremely difficult to implement in tools.
Quick heads-up: your HN bio is empty, I'd have no idea where to watch for them tweets :-)
Compilers generally require flags to enable features. There hasn't been a post-MVP feature that has widespread enough adoption that it would make sense for us to enable it by default.
For developers, the best thing is to make separate builds with the sets of features you want, and pick the right build using something like wasm-feature-detect
https://github.com/GoogleChromeLabs/wasm-feature-detect
There is some discussion on something like "fat binaries" which would contain multiple builds and pick between them,
Glad to see that feature finally getting more traction. This will be extremely useful for languages such as Go.