Scripting Languages and Compiled Languages in WebAssembly
A Bird’s Eye View of Programming Languages
Taking a look at the most popular programming languages, we get a glimpse of three different types of programming languages:
In the top 10, we see a few compiled languages, a pair of virtual machine languages, and five scripting languages.
In the top ten list, C++ (#5) and C (#10) are languages compiled to native. Rust and Go are two other popular compiled languages that didn’t quite make the top 10. In general, these languages are compiled to a binary format specific to the architecture and operating system. A compiled language does not need an interpreter or virtual machine to execute the program.
Compiled languages have enjoyed early WebAssembly support. In fact, all four (C, C++, Rust, and Go) can be compiled to WebAssembly. This might seem surprising, as these languages are typically compiled per architecture and OS. That is, a C program usually must be compiled one way to run on ARM and Linux, and compiled a different way to run on macOS with an Intel processor (and sometimes the code must be changed per platform). But when they are compiled to WebAssembly, they can run on any WebAssembly runtime regardless of operating system, architecture, or other similar low-level details.
When it comes to WebAssembly compiler support, Rust and C are the furthest along, each with impeccable support. C++ support comes by way of the C compilers, and consequently is also well supported. Go’s official distribution (owned by Google) is a little behind, but the TinyGo project has made up the difference. All of these languages are production-ready on WebAssembly.
Effectively, compiling one of these “native” languages to WebAssembly means they behave more like virtual machine languages.
Virtual Machine Languages
In the top ten, there are two virtual machine languages: Java (#2) and C# (#5). Other popular virtual machine languages include Scala, F#, and Kotlin. These languages are compiled, but not to native code. They are compiled to an intermediate format generically called “bytecode.” That code is then fed into a special runtime or virtual machine (the JVM for Java or the CLR for C#).
.NET (including C#, F#, and ASP.net) has excellent support for WebAssembly in the browser, and we know that the Microsoft team is working on many other enhancements. Kotlin support is coming along rapidly, and there are a number of projects for Java and Scala.
As these languages are ported to WebAssembly, they will no longer need their language-specific runtimes. For example, Kotlin will not need the JVM. It will be compiled directly to WebAssembly that can be executed directly on a WebAssembly runtime.
Right now support for these languages is less robust than the compiled languages we looked at above (though all are rapidly improving). But if the momentum keeps as it is today, we will soon see many virtual machine languages compiling to WebAssembly.
Scripting (Interpreted) Languages
While work on WebAssembly support for compiled languages has focused on compiling the programs themselves to WebAssembly, the work with scripting languages has focused on compiling the scripting runtime to WebAssembly. In this model, the engine is loaded into the WebAssembly runtime, and then the scripts are loaded into the engine. The two-tier execution model this presents is more complicated than the compiled languages. But by sticking to the familiar, this model is also the easiest for developers in that language. For example, they do not need to learn how to compile their previously interpreted code.
As of January, 2022, both Ruby and Python can now compile their respective runtimes to WebAssembly. While support for Wasm is early in both of these, we believe they will mature very quickly now that the hard part is done. (We have a few blog posts on the horizon to show Ruby and Python in action!)
Finally, PHP is slightly behind the other scripting languages in support. A few non-official projects have added limited support for executing PHP in the browser by loading a WebAssembly-compiled PHP interpreter into the browser and executing code there. Some of the examples are exciting. PHP, with it’s request/response model, would be an excellent language for authoring WebAssembly cloud applications. We are excited about the future prospects.
Scripting Languages May Become Compiled Languages
There is one final observation regarding current differences in languages. With WebAssembly, compiled languages like C, Rust, and Go effectively become virtual machine languages. Can we expect the same thing to occur in the scripting world? Will scripting languages be pre-compiled into WebAssembly binaries?
There are some reasons to think that the answer to this question will be yes.
- A shared model of execution makes running WebAssembly simpler. And the two-stage loading of scripting languages could be replaced by a single stage.
- Performance, too, is an issue. It is hard to optimize a two-stage process as much as one can optimize a single-stage process.
- Code redundancy is a third reason: Right now, every WebAssembly-targeted Python script must ship with a complete copy of the Python environment. By compiling the end code to Python, unused parts of the Python environment could be stripped out at compile time, making smaller application sizes
- AssemblyScript already is leading the way by sharing the design of TypeScript, but compiling directly to WebAssembly bytecode.
Support for executing popular languages in WebAssembly is growing fast. We surveyed the top 10 languages, but if we were to expand to the top 20, we would see the same pattern playing out. Many languages, popular and esoteric, are gaining WebAssembly support. As WebAssembly itself gains new features, we have every reason to believe that WebAssembly will become a popular target for an increasing array of languages.