Rlang : a Ruby-like language compiled to WebAssembly
Rlang is meant to generate fast and uncluttered WebAssembly code from the comfort of the Ruby language.
Rlang is actually two things: 1) a subset of the Ruby language and 2) a compiler transforming this Ruby subset in a native, fully runnable WebAssembly module.
So in summary what Rlang does is:
Rlang source code → Rlang compiler → WebAssembly bytecode
Rlang can be seen as a foundational language that can help you quickly develop and debug high performance WebAssembly modules. For the rationale behind the creation of Rlang see below.
This is still a young project but Rlang has already been successfully tested with some real code such as the dynamic memory allocator provided with the Rlang library. It will keep improving over time, always with the goal of generating crisp and uncluttered WebAssembly code.
If you want to help with Rlang see How you can help.
Dependencies
- WABT toolkit: the rlang compiler can generate both WebAssembly source code (WAT file) and WebAssembly bytecode (WASM file). To generate WASM bytecode the rlang compiler uses wat2wasm. This utility is part of the WABT toolkit
- wasmer runtime (optional): Wasmer is a fast WebAssembly runtime. You'll need it if you want to run the test suite from the source repo. You can also use it to run the compiled WASM code generated by the rlang compiler. You can get Wasmer at wasmer.io
Rlang has also been successfully tested with the Wasmtime WebAssembly runtime.
Installing Rlang
Rlang is available as a gem from rubygems.org. So simply run the following command to install it:
$ gem install rlang
Alternatively, if you clone this git repo and play with the Rlang source code you can generate your own local gem and install it as follows:
$ bundle install
$ gem build rlang.gemspec
$ gem install --local rlang-x.y.z.gem
To check that the installation went well, run rlang --help
and see if the help message displays correctly.
A Quick example
An example is always worth a thousand words, so here is a quick one showing you how to compile some Rlang code and run it from your browser. Since Chrome, Chromium, Firefox and Safari embed a WebAssembly runtime it is the easiest way to test your compiled Rlang code.
Navigate to the Fibonacci directory in examples/fib and download the three files from this directory: fib.rb, index.html, server.rb. Alternatively you can git clone the repo and go directly in that directory.
Open fib.rb with your favorite editor and see for yourself that it really looks like Ruby code :-). Then from a shell session:
# Compile the fib.rb file to Wasm bytecode
$ rlang --wasm -o ./fib.wasm ./fib.rb
# Launch the mini http server
$ ruby server.rb
Point your browser to http://localhost:8080, a simple page should display inviting you to type an integer value then click run to obtain the corresponding fibonacci term.
That was easy, right ?
The Rlang language
Ruby features supported by Rlang are detailed in the Rlang Manual
You can look at the rlang test suite in test/rlang_test_files to get a flavor of the subset of Ruby currently supported.
For a more involved example of Rlang code, I invite you to look at the dynamic memory allocator provided with the Rlang library.
The rlang compiler
The Rlang compiler can be invoked through the rlang
command. See the Rlang Compiler Documentation for more details about the command line options.
Keep in mind that Rlang is NOT a Ruby interpreter or a Ruby VM executing some kind of bytecode. It does actually statically compile the Rlang language to WebAssembly code pretty much like gcc or llvm compiles C/C++ code to machine assembly language.
rlang simulator
COMING SOON One of the big benefits of Rlang being a subset of the Ruby language is that you can actually run, test and debug your Rlang code as you would for normal Ruby code. This can be a big boost for your productivity.
Why Rlang?
This project was created out of the need to develop a Virtual Machine written in WebAssembly capable of interpreting the Rubinius bytecode. And yes, ultimately run a native Ruby VM in a browser :-)
After a first proof of concept written directly by hand in WebAssembly (WAT source code) it became clear that writing a full fledged VM directly in WebAssembly was going to be tedious, complex and unnecessarily painful.
Sure I could have written this VM in any of the language that can already be compiled directly to WebAssembly (C, C++, Rust, Go,...) but being fond of Ruby since 2000 I decided that I would design a compiler capable of transforming a subset of the Ruby language directly into WebAssembly with a minimum overhead.
So in a nutshell: the goal of Rlang is to let you develop efficient WebAssembly code with a reasonably high level of abstraction while keeping the generated WebAssembly code straightforward, human readable and slim.
Why the name Rlang?
Yes I hear you: Rlang is already the name of the R language so why use that name and aren't you introducing some confusion? Well for one I couldn't resist using that name to honor software engineering history (see below) and because, after all, the intersection between the Ruby/WebAssembly community and the R language community focused on data processing and machine learning must be quite small to say the least.
The name Rlang itself is a tribute to Slang, a subset of the Smalltalk language that can directly translate to C. It was created in 1995 to bootstrap the development of the virtual machine of Squeak, an open-source Smalltalk programming system. I highly encourage anyone interested in the history and the technology of virtual machines to read both the Back to the future article as well as the now legendary Blue Book explaining how the Smalltalk-80 Virtual Machine and Language were designed in the 80s. I would actually go as far as saying that you don't really know what (virtual) machines are until you have read this book :-)
How you can help
- Test Rlang installation on different platforms (Linux, Mac, Windows) and different Ruby versions (Ruby 2.2 and above)
- Write some real Rlang application code, compile it and test it.
- Improve the documentation if you find it unclear or want to enrich it with further examples and tips
- Growing the Rlang library that is still quite basic. For instance you can write new methods from the String class or the Array class,...).
- If you feel like digging into the Rlang parser and Wasm code generator you can extend the Rlang language itself
- And of course writing tests for the parts of the code not yet covered is always welcome (running "rake test" also generates code coverage information)
Credits
A big thanks to:
- @whitequark for a fantastic Ruby parser
- The Wasmer team as well as the authors of the Ruby Wasm extension of Wasmer