Fable: Compiling F# modules to WebAssembly

Created on 12 Oct 2018  路  12Comments  路  Source: fable-compiler/Fable

Continue discussion started here: https://github.com/fable-compiler/Fable/pull/1598#discussion_r224482819

I won't be able to start working on this very soon but being able to compile some F# modules to WebAssembly is an exciting possibility that should be already possible, so let's list here the necessary points to make it easier to coordinate for contributors.

Pinging @ncave, and also @xtuc, @SanderSpies because they've kindly offered their help on Twitter :)

  • [ ] Wasm only supports numbers atm and we're not planning to compile a full runtime like mono-wasm does, so for now I guess we'll have to use a separate F# project (with some shared interfaces)repl and import it manually, as we already do for web workers, etc.
  • [ ] Add an alternative Replacement module for wasm. I guess for now this module only needs to deal with Array, arithmetic and numeric conversion/equality operations.
  • [ ] Bring back type annotations for numeric, arrays and boolean types. Babel can understand them but we're not sure if it can produce them. Can you confirm this @xtuc?
  • [ ] If we can output something similar to TypeScript (basically ES6 + type annotations) then we can pass this to AssemblyScript pipeline, probably through their Webpack loader.

This is a very rough draft for now, let me know if you want to add/modify any point or any other comment you may have.

discussion

Most helpful comment

It would likely take Alphonso or one of his immediate team to tell us how much work he/they feel it would take to convert the Fable AST to a LLVM or C-like AST instead of the Babel AST.

Well, truth is I'm not a clang expert but my feeling is it would require a LOT of work :) Also, after several years working with Fable I've realized it's not only a matter of having a compiler from one language to another, but about the _development experience_ (if it takes more effort to use the transpiler than the native language, nobody will use it) and this is what it takes the most work. So atm I don't envision any branch of Fable targeting LLVM or any other language.

Now, as it sometimes happens, a PR will come out of the blue to contradict this, but I'd be very happy in that case :)

All 12 comments

I'm exited to hear that you want to compile to WebAssembly :+1:

Wasm only supports numbers atm [...]

While it's true, it's not accurate. Using glue code in JavaScript, you are able to pass more complex types by manipulating wasm's memory.

TextDecoder for example is very helpful for passing strings.

I can recommend you to look at wasm-bindgen for inspiration.

Bring back type annotations for numeric, arrays and boolean types. Babel can understand them but we're not sure if it can produce them. Can you confirm this @xtuc?

Babel 7 is now able to generate TypeScript given TS* nodes, which could be feed into AssemblyScript. Using @babel/types you should be able to generate those nodes.

However, this seems like a complicated pipeline. Note that AssemblyScript will typecheck the generated TypeScript code.

You mean Babel 7 can generate *.d.ts files? But this only interface, type, class and method signatures and I don't think this really help producing compatible AS code. Also AS has some limitation for type inferring especially for generics.

@MaxGraey Babel can generate TS syntax, as far as I know, .d.ts files are just regular TypeScript files (but more like c header file?). I guess that would work with a bit of scripting.

@xtuc I think you know better of course. The only thing, pure typescript does not support for example integer types and some other things, which can significantly affect performance and not give a significant speed advantage.

A dream come true would be to see F# just compiling to rust and thus giving F# a native compilation target and wasm all in one go, the language semantics of rust and F# are pretty similar overall since they're both in the ml family, but the borrow checker is probably where the main challenge would be, at least if you still want garbage collection, but if garbage collection isn't a strict requirement, rust could be a doable compilation target that may be worth considering.

Rust semantics are much more stricter that F#, I don't think it's possible.

True, the borrow checker would make things tough, but not impossible. Ocaml is another option. https://github.com/SanderSpies/ocaml/tree/wasm/wasmcomp

How about rather than transpiling to rust, transpiling the Fable AST to a more generic LLVM AST, which could then perhaps still generate WebAssembly as an alternate backend, or even transpiling to "just C" and then being able to use GCC, Clang, or Emscripten (or whatever C dialect).

THis last is what the Nim language does, and it doesn't have to be a "complete" conversion but just to some form of a C-- that supports the features we require. In that way, we get the optimization features of the LLVM or C/C++ compiler for free, while still able to use whatever backend those support to get WebAssembly.

One thing that will have to be overcome no matter what path is chosen is memory management; Nim, which also has a JavaScript backend and up to now has had Garbage Collection, is now considering scrapping the GC in favour of a more Swift-like automatic reference counting (with some improvements); however, would F#/Fable really care what system was used under the covers as long as available memory of a given size gets allocated when asked for it and somehow gets deallocated when no longer used. Automatic deallocation as proposed for Nim would appear to do that for F#/Fable as well.

It would likely take Alphonso or one of his immediate team to tell us how much work he/they feel it would take to convert the Fable AST to a LLVM or C-like AST instead of the Babel AST.

If this could be done, it truly would be exciting times, with F#/Fable almost becoming "one language to rule them all" (other than for functional programming purists who will keep harping about not having type classes and performant higher-kinded-types).

It would likely take Alphonso or one of his immediate team to tell us how much work he/they feel it would take to convert the Fable AST to a LLVM or C-like AST instead of the Babel AST.

Well, truth is I'm not a clang expert but my feeling is it would require a LOT of work :) Also, after several years working with Fable I've realized it's not only a matter of having a compiler from one language to another, but about the _development experience_ (if it takes more effort to use the transpiler than the native language, nobody will use it) and this is what it takes the most work. So atm I don't envision any branch of Fable targeting LLVM or any other language.

Now, as it sometimes happens, a PR will come out of the blue to contradict this, but I'd be very happy in that case :)

For the people who want to compile F-Sharp into Rust: Gluon
It is not exactly compiling into Rust, while offering a lot of its advantages.
Gluon can consume Rust functions like its own.

I know this is not helping further here with WebAssembly, just got triggered and wanted to share. :sweat_smile:

And this here is obviously already a method to compile F# into WebAssembly: Bolero

Targeting LLVM is doable, but far from easy, especially when you have to create your own semantics preserving transformations, runtime and garbage collector, ffi, etc.

Closing as there are no plans at the moment to compile to WebAssembly (at least not directly).

Was this page helpful?
0 / 5 - 0 ratings