remko / waforth

Small but complete dynamic Forth Interpreter/Compiler for and in WebAssembly
https://mko.re/waforth
MIT License
497 stars 27 forks source link

Implementing other languages with the same approach #48

Closed jpaquim closed 2 years ago

jpaquim commented 2 years ago

First of all, major kudos and thank you for putting this together, I've been fascinated with this project since I found it, after finally diving a bit deeper into Forth. To be honest I can't get it out of my head for a few weeks now, I'm just filled with ideas for how I can use this kind of approach for other projects.

Is there any other Wasm language/runtime using the same kind of function dynamic linking? i.e. compiling words/functions to Wasm functions, loading them into a function ref table, and immediately having them available for further use in the language? I'm thinking this might be a great way to go for implementing other languages using the same kind of Forth-like hybrid interpreter-compiler runtime, such as Rebol/Red, or even other more dynamic languages based on a JIT compiler, have you by chance given this any thought @remko?

remko commented 2 years ago

@jpaquim Thanks! Very nice to hear this work has inspired you!

I don't know if other projects take this approach, but I must admit i'm not following everything that's going on in the WASM scene. WAForth is pretty hard-core because the compiler is implemented in WebAssembly as well; it's probably easier to use a high-level language to implement a MyLanguage-to-WASM compiler (or use an existing one, possibly cross-compiled to WebAssembly itself). I'm pretty sure other WASM compilers support dynamic loading too, since there are proposals to improve things such as position-independent-code. I don't know if you can do interactive-style development with any of these, though.

jpaquim commented 2 years ago

Inspired is an understatement šŸ˜› My feeling is that your approach could also work very well for something like a variant of Lisp or Rebol/Red, where the level of dynamism is rather high, and a compiler is typically used as part of the runtime.

I think even just the Wasm code generation and dynamic loading part of your code could make for a pretty sweet library/libraries for people looking to implement cool stuff using Wasm šŸ™‚

I was thinking of diving deep into your implementation, and doing something similar using Zig as the implementation language, given it's great Wasm support including inline assembly using Wasm/Wat (derived from LLVM).

remko commented 2 years ago

@jpaquim here is a link that will probably interest you. It talks about some of the same techniques used in WAForth, and comes with Scheme examples.

jpaquim commented 2 years ago

Thank you very much @remko, definitely very interesting and more food for thought. I hadn't considered using Wizer at all but it seems very powerful for the static linking approach he describes. Curious to see his next posts on the subject!

BTW, did you happen to experiment with a C implementation or similar before going for the raw Wat? If so, any particular reason that nudged you over to using Wat directly instead?

remko commented 2 years ago

I didn't experiment with a C implementation. I don't think there's a good technical reason to use WebAssembly directly, except perhaps direct control over the function table (the link above should show you how to work around this). I just wanted to see how far I could take the minimalism, and it's a good WebAssembly learning opportunity šŸ˜‰ Forth's simplicity lends itself to such an approach, but for any higher-level language, I'd probably write the system in a high-level language as well. Personally, Iā€™d settle for any language that compiles to WebAssembly without a runtime. C would be fine, but Zig might be more fun and more interesting.