The Birth & Death of JavaScript wasn't talking about WASM, it was talking about Asm.js, which crucially differs from WASM by being a backwards-compatible subset of JavaScript amenable to JIT compilation. The goals of these standards look similar if all you care about is transpiling c and running it on a browser, but Asm.js worked everywhere from day zero modulo performance; WASM continues to be a moving target.
in the LISP 1.5 Programmers's Manual there's a single page that defines eval/apply in lisp code. I was exploring something similar for OOP, what's the minimal set of features needed to bootstrap objects and method dispatch.
Thanks! Goblins is actually our main project and Hoot is the side project so we can deploy it on the web. Scheme is a really nice language and when you add in some modern features you can do some pretty neat things!
Meta comment: I love that this is on a self-hosted forge.
I'm hoping that AT protocol-based self-hosted forges let us have the independence of self-hosted but the networking and gamification of GitHub. Maybe something like Tangled will bring that, though I haven't looked too deeply.
This isn't quite a standards conforming Scheme just yet.
On the other hand, Hoot supports WASM-GC on release [0], and has had wasm support for a few years now. (Though Safari support has been a pain point - they've found a few bugs in WebKit's wasm support.)
Just eyeballing it really quickly, it doesn’t look like it’s got the built-ins you’d want to quickly built a REPL (i.e. read or eval). It’s not really Scheme, yet.
It’s written in C, so you could compile that to wasm and then compile & run all inside the browser (I guess, assuming wasm is cool with that sort of thing, not a wasm guy here).
You can do that kind of JIT code generation with WASM but you need to compile a separate module and load and link things up in JS (doable but not technically within pure WASM, so it won’t work in standalone runtimes)
People do not generally want to capture the entire continuation, they want delimiters. Delimited continuations are a superset of call/cc and vastly more useful, more performant and easier to understand.
The call/cc interface is completely backwards as well. It's like throw/catch but the exception handler is specified by throw instead of catch. Totally mind bending and unintuitive.
This continuation business is just resumable exceptions. Would have been a lot easier for people to understand and use had they just called it that.
try:
print(10 + throw("error"))
catch error, continuation:
continuation(10) # Makes throw return 10, prints 20
Despite call/cc being generally understood as not good it's still something you would expect to work in a Scheme implementation. In the Scheme-on-Wasm implementation I work on we emulate call/cc in terms of delimited continuations. Passes r7rs benchmaks that make use of call/cc.
Seems kind of backwards to call them resumable exceptions because delimited continuations are the primitive upon which an exception system can be built but yeah maybe it would make sense to programmers that already understand exceptions. I like the prompt metaphor, myself. https://www.gnu.org/software/guile/manual/html_node/Prompts....
> we emulate call/cc in terms of delimited continuations
Seems reasonable.
> I like the prompt metaphor, myself
Me too. I really like Guile's prompts. They are delimited and structurally similar to my example above, only they're even more powerful since they have tags which lets programmers unwind to specific delimiters!
I'm implementing this stuff in my lisp right now. The prompt primitive pushes a special continuation marker stack frame which also contains a value. The tagged prompts use symbols as the tag, untagged prompts use nil.
> Seems kind of backwards to call them resumable exceptions
This is is the analogy that enabled me to finally understand this continuation stuff. Alexis King's keynote shows that they are equivalent:
Nope. I was thinking about implementing call/cc; there is a neat trick involving first doing a CPS transformation to the source, then providing call/cc as a builtin function that more-or-less just grabs the continuation argument and returns it. This would slot pretty easily in between expansion and code gen and the code generator would remain mostly untouched.
In case you are interested I wrote a minimal OOP runtime in wasm-gc (using wasm text format) here: https://marianoguerra.org/posts/bootstrap-post-collapse-oop-...
I also wrote a forth in wasm by hand here: https://github.com/marianoguerra/ricardo-forth
And a wasm compiler that fits in a tweet: https://wasmgroundup.com/blog/wasm-compiler-in-a-tweet/
I'm also the co-author of a book that shows you how to write a compiler that targets wasm for a small languaje using js: https://wasmgroundup.com/
Here's a direct link to the wasm text format for the OOP and forth implementations:
- https://github.com/marianoguerra/mclulang/blob/main/wat/fatt...
- https://github.com/marianoguerra/ricardo-forth/blob/master/s...
The Birth & Death of JavaScript wasn't talking about WASM, it was talking about Asm.js, which crucially differs from WASM by being a backwards-compatible subset of JavaScript amenable to JIT compilation. The goals of these standards look similar if all you care about is transpiling c and running it on a browser, but Asm.js worked everywhere from day zero modulo performance; WASM continues to be a moving target.
Wasm has long supported everything you could do with asm.js. But wasm is about much more than C to browser. That's why it's still evolving.
Asm.js runs on the main thread, WASM runs in its own thread.
Not exactly true WASM compilcation is in a different thread, but the execution happens on the same thread as JS if you don't do any webworker stuff.
Edit: https://apryse.com/blog/how-to-enable-webassembly-threads
a minimal OOP runtime
What does this mean?
in the LISP 1.5 Programmers's Manual there's a single page that defines eval/apply in lisp code. I was exploring something similar for OOP, what's the minimal set of features needed to bootstrap objects and method dispatch.
You might find "Open, Extensible Object Models" by Ian Piumarta and Alessandro Warth interesting.
Found a link: https://tinlizzie.org/VPRIPapers/tr2006003a_objmod.pdf
Related: Guile Hoot is a Scheme to Wasm compiler written in Scheme.
https://spritely.institute/hoot/
Thanks for including this.
Hoot looks fantastic. There's a side project, Goblins https://spritely.institute/goblins/ that does distributed development too.
Great to see that people are still supporting Scheme tools. There's a lot of utility here, even if people (and job adds) go for the "latest" tools.
Thanks! Goblins is actually our main project and Hoot is the side project so we can deploy it on the web. Scheme is a really nice language and when you add in some modern features you can do some pretty neat things!
Meta comment: I love that this is on a self-hosted forge.
I'm hoping that AT protocol-based self-hosted forges let us have the independence of self-hosted but the networking and gamification of GitHub. Maybe something like Tangled will bring that, though I haven't looked too deeply.
Not AT protocol based (I think) but have you looked at Radicle? https://radicle.xyz
Wouldn't a Scheme to WASM compiler in Scheme make more sense, providing the capability to do something like Gerbil Scheme?
I like wasm, but the idea of running an app in the browser is a real bummer. What kind of native interpreters are there?
https://wasmtime.dev/
Node.
Can it be used as a interpreter once compiled to not need a compiler?
This isn't quite a standards conforming Scheme just yet.
On the other hand, Hoot supports WASM-GC on release [0], and has had wasm support for a few years now. (Though Safari support has been a pain point - they've found a few bugs in WebKit's wasm support.)
[0] https://spritely.institute/news/hoot-0-6-1-released.html
Thankfully, Safari and iOS now have the necessary bug fixes to run wasm binaries generated by hoot without issue.
Just eyeballing it really quickly, it doesn’t look like it’s got the built-ins you’d want to quickly built a REPL (i.e. read or eval). It’s not really Scheme, yet.
It’s written in C, so you could compile that to wasm and then compile & run all inside the browser (I guess, assuming wasm is cool with that sort of thing, not a wasm guy here).
You can do that kind of JIT code generation with WASM but you need to compile a separate module and load and link things up in JS (doable but not technically within pure WASM, so it won’t work in standalone runtimes)
I couldn't find evidence of an interpreter on the scm2wasm github page, but I only did a shallow look.
Hoot (uses Guile Scheme), mentioned above, has a working interpreter, to quote...
With call/cc ??
Is there a reason to implement this other than standards compliance?
There are plenty of problems with it:
https://okmij.org/ftp/continuations/against-callcc.html
People do not generally want to capture the entire continuation, they want delimiters. Delimited continuations are a superset of call/cc and vastly more useful, more performant and easier to understand.
The call/cc interface is completely backwards as well. It's like throw/catch but the exception handler is specified by throw instead of catch. Totally mind bending and unintuitive.
This continuation business is just resumable exceptions. Would have been a lot easier for people to understand and use had they just called it that.
Despite call/cc being generally understood as not good it's still something you would expect to work in a Scheme implementation. In the Scheme-on-Wasm implementation I work on we emulate call/cc in terms of delimited continuations. Passes r7rs benchmaks that make use of call/cc.
Seems kind of backwards to call them resumable exceptions because delimited continuations are the primitive upon which an exception system can be built but yeah maybe it would make sense to programmers that already understand exceptions. I like the prompt metaphor, myself. https://www.gnu.org/software/guile/manual/html_node/Prompts....
> we emulate call/cc in terms of delimited continuations
Seems reasonable.
> I like the prompt metaphor, myself
Me too. I really like Guile's prompts. They are delimited and structurally similar to my example above, only they're even more powerful since they have tags which lets programmers unwind to specific delimiters!
I'm implementing this stuff in my lisp right now. The prompt primitive pushes a special continuation marker stack frame which also contains a value. The tagged prompts use symbols as the tag, untagged prompts use nil.
> Seems kind of backwards to call them resumable exceptions
This is is the analogy that enabled me to finally understand this continuation stuff. Alexis King's keynote shows that they are equivalent:
https://youtu.be/TE48LsgVlIU
Everybody understands exceptions. Delimited continuations are exceptions that not only unwind the stack but also back it up into a callable value.
No, but with tail call (using underlying WebAssembly tail call).
Nope. I was thinking about implementing call/cc; there is a neat trick involving first doing a CPS transformation to the source, then providing call/cc as a builtin function that more-or-less just grabs the continuation argument and returns it. This would slot pretty easily in between expansion and code gen and the code generator would remain mostly untouched.