# gl_wasm
[![Package Version](https://img.shields.io/hexpm/v/gl_wasm)](https://hex.pm/packages/gl_wasm)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/gl_wasm/)
Create binary WebAssembly modules in Gleam.
## Goals
- Support for the WebAssembly 2.0 (draft) specification, giving priority to
features that are useful for functional languages, such as GC and return call.
- Make it as difficult as is reasonably possible to generate invalid
WebAssembly.
- Eliminate unnecessary ceremony and performance bottlenecks.
## Possible goals
- Parsing binary WebAssembly modules.
- Debugging support, e.g. DWARF.
- Component Model and WASI support.
## Non-goals
- WASM optimization.
- Support for WAT (WebAssembly Text format).
## Progress
### Features
- [x] Building modules
- [x] Registering types
- [x] Building functions
- [x] Importing functions
- [x] Exporting functions
- [x] Type validation
- [ ] Type recursion and subtyping
- [x] Global initialization
- [x] Validation for global initialization
- [ ] Advanced validation for break/return
- [ ] Features related to unimplemented sections
- [x] Use bytes_tree instead of byte_array.concat & friends
- [x] JavaScript target support (primarily number type encoding)
- [x] Output stream abstraction
### Sections
- [x] Type
- [x] Function/code
- [ ] Table
- [ ] Memory
- [x] Global
- [ ] Element
- [ ] Data/data count
- [x] Start
- [x] Export
- [x] Import
- [ ] Custom
- [x] Name
### Instructions
- [x] General control flow
- [x] Function calls
- [x] General reference instructions
- [x] Struct
- [ ] Array
- [ ] i31
- [ ] Extern
- [ ] Table
- [ ] Memory
- [x] i32 and i64 encoding
- [x] f32 and f64 encoding
- [x] Common i32, i64, f32, f64 instructions
- [ ] Numeric conversions, truncations, etc.
- [ ] v128
## Usage
```sh
gleam add gl_wasm
```
This example generates a module that imports an "add" function and uses that to
implement a "double" function which it exports.
```gleam
import gl_wasm/wasm
import gleam/io
import gleam/list
import gleam/option.{Some}
import gleam/result
import simplifile
pub fn main() {
case generate_wasm() {
Error(message) -> io.println_error(message)
Ok(_) -> Nil
}
}
fn file_output_stream(fname) {
let output_stream =
wasm.OutputStream(
stream: fname,
write_bytes: fn(fname, bytes) {
simplifile.append_bits(fname, bytes)
|> result.replace(fname)
},
close: fn(fname) { Ok(fname) },
)
let _ = simplifile.write_bits(fname, <<>>)
output_stream
}
fn generate_wasm() {
// Create a ModuleBuilder that writes to the file "out.wasm"
let mb = wasm.create_module_builder(Some("Doubler"))
// Register the "add" function type and import "math.add"
use #(mb, type_index_add) <- result.try(wasm.add_type(
mb,
wasm.Func(Some("add_type"), [wasm.I64, wasm.I64], [wasm.I64]),
))
use mb <- result.try(wasm.import_function(
mb,
type_index_add,
Some("add"),
wasm.ImportSource("math", "add"),
))
// Register the "double" function type and generate its code
use #(mb, type_index_double) <- result.try(wasm.add_type(
mb,
wasm.Func(Some("double_type"), [wasm.I64], [wasm.I64]),
))
use #(mb, fb) <- result.try(wasm.create_function_builder(
mb,
wasm.FunctionSignature(type_index_double, Some("double"), Some(["n"])),
))
use fb <- result.try(list.try_fold(
over: [wasm.LocalGet(0), wasm.LocalGet(0), wasm.Call(0), wasm.End],
from: fb,
with: wasm.add_instruction,
))
use mb <- result.try(wasm.finalize_function(mb, fb))
// Export the "double" function
use mb <- result.try(wasm.add_export(mb, wasm.ExportFunction("double", 1)))
// Write the WebAssembly to file
wasm.emit_module(mb, file_output_stream("out.wasm"))
|> result.replace_error("Error writing to file")
}
```
The disassembled WebAssembly Text (WAT) representation looks like this:
```
(module $Doubler
(type $add_type (func (param f64 f64) (result f64)))
(type $double_type (func (param f64) (result f64)))
(import "math" "add" (func $add (type $add_type) (param f64 f64) (result f64)))
(export "double" (func $double))
(func $double (type $double_type) (param $n f64) (result f64)
(call $add
(local.get $n)
(local.get $n)
)
)
)
```
Further documentation can be found at <https://hexdocs.pm/gl_wasm>.
## Development
```sh
gleam run # Run the project
gleam test # Run the tests
```