I've got so much other stuff I'd rather learn and code I'd rather write (C/wasm backend for my language), but I've also started job hunting and probably should understand how this latest fad works. Neural networks have long been on my todo list anyway.
Details on the representation.
https://github.com/soegaard/webracket/blob/main/compiler.rkt...
I am more or less only using the linear memory for the JavaScript FFI. FASL-encoded values are passed back and forth to JavaScript.
Of course both projects have the same maintainer if I recall, Jens Axel Søgaard is a rockstar :)
Original developer of Whalesong was Danny Yoo. https://www.hashcollision.org/whalesong/
There was also this: https://docs.racket-lang.org/racketscript/
Dave Herman worked on various JS-related libraries for Racket (or PLT Scheme) before he was involved with Rust.
Whalesong used the built-in bytecode compiler and compiled the bytecode to JavaScript. Reusing the bytecode compiler is in principle a good idea - but each time the bytecodes are changed, Whalesong needs to be updated.
And after the move to Chez Scheme as backend, the bytecode compiler is no longer a part of the main compilation path.
Is Racket bytecode different?
Racket is not [1]. It's just the internal representation that the compiler uses. Sort of like marshalling in Python.
[0] https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.ht...
[1] https://docs.racket-lang.org/raco/API_for_Making_Bytecode.ht...
Changes to the bytecode representation were indeed rare also in Racket.
The Whalesong project was written as part of a dissertation - and when people graduate and get jobs, projects are often abandoned.
I wonder how much efficient would such wasm be compared to native itself theoretically?
I really like libriscv as well, what are your thoughts on libriscv and now the recent project created by legendary fwsgonzo about looongarch.
Although I would say that libriscv/loongarch are more focused on trying to start the fastest as much as possible instead of pure performance (for which if atleast for the purpose of sandboxing, fwsgonzo has also created tinykvm which is really quite close to native performance)
It's been a really fun side project.
I do think there is a market for something like this - optimizing an existing language for WASM, or ephemeral networked code delivery in general, can be really hard. And a statically typed, WASM-oriented, very familiar high-level language, that can give very good static errors, and quickly run in a secure sandbox might be a good target for LLM-generated code.
It's still early days for the WebRacket project.
Racket is a huge language, so be patient wrt features.
To keep motivation high I decided to implement a subset that can be used to built practical applications - and then extend the supported features from there. Hopefully, this strategy will also lead to some early adopters that can help me prioritize which features to add.
Some features are simply "more of the same". In this category falls more types of hash tables. Supporting bignums are also a matter of just doing it.
Other features require more work. I have already done some work on implementing modules in terms of linklets. When linklets/modules work, we can reuse the existing implementation of regular expressions.
Adding continuation marks and delimited continuations require adding a CPS-pass. This is certainly doable. Postponing it has been great though. Having a direct style compiler means the generated code follows the structure in the input source code. And that makes debugging easier. Now that bugs have become rarer, it makes sense to look at CPS.
Enjoy.
/Jens Axel
The representation is explained here:
https://github.com/soegaard/webracket/blob/main/compiler.rkt...
Internally the compiler uses a series of passes implemented using Nanopass.
(generate-code
(flatten-begin
(closure-conversion
(anormalize
(categorize-applications
(assignment-conversion
(α-rename
(explicit-case-lambda
(explicit-begin
(convert-quotations
(infer-names
(flatten-topbegin
(parse
(unexpand
(topexpand stx)))))))))))))))
The code generator is inspired by "Destination-driven Code Generation"
by Dybvig, Hieb and Butler. There are some differences however. The code
generator in the paper generates "flat" code (assembler) whereas I
generate nested Web Assembly instructions.This approach generates reasonable code without having to implement a register allocator. Also, I believe I saw a Wasm to Wasm compiler that improved register allocation (maybe it was a switch for wasm-tools?).
If (when?) WebRacket becomes a success, we can always switch out individual passes.
Have you considered targeting the stack switching proposal?
[1]: https://github.com/ocsigen/js_of_ocaml/blob/1b1fcf7b06c12324... [2]: https://github.com/WebAssembly/js-promise-integration/blob/7...
If I need a CPS-pass for continuation marks, I might as well use it for continuations as well.
It would be great if it were possible to avoid a CPS-pass though.
However, I don't see an obvious way of attach and probe continuation marks to the continuations (including the current one).
I am not an expert in continuation marks, so I'll just link to this presentation by Matthew Flatt (which you probably already know).
https://github.com/WebAssembly/meetings/blob/main/stack/2021...
An example page (not mine) of it running in the browser is here: https://actondev.github.io/s7-playground/
I really hope the racket effort gains traction too! Excited to see this. In comparison, s7 is much more minimal. Though this also means the FFI is dead simple too, so extending it and bridging to js functions is much easier, and everything in s7 is available now in WASM - CL macros, keywords, hashtables, first class environments, continuations, etc
dfajgljsldkjag•2w ago
d_philla•2w ago
mlinksva•2w ago
volemo•2w ago
kg•2w ago
soegaard•2w ago
This forces an Racket implementation to make continuations explicit. And that will most likely mean a WebAssembly backend will be slower than the native backends.
davexunit•2w ago
gcr•2w ago
- Modules aren't implemented yet, but are high on the list
- Continuation-based control flow isn't supported yet, including break and promises. Tail calls are supported though.
- No support for complex numbers, bignums, weak hashtables, immutable hashtables, prefab structs, regexp, or file I/O support
Most of the rest of racket/base should work, according to the README. There's also a FFI for javascript, including bindings for Math, DOM, Canvas, MathJax, XTermJS, and JSXGraph. Overall feels like you can use most of the language right now unless you need odd Racket-isms or call/cc.