Light & fast WAT compiler.
Provides bare minimum WAT to WASM compilation without unnecessary syntax complexities (see limitations).
Useful as WASM API layer for hi-level languages, also for dynamic (in-browser?) WASM compilation.
Size (gzipped) | Performance (op/s) | |
---|---|---|
watr | 3.8 kb | 1900 |
wat-compiler | 6 kb | 135 |
wabt | 300 kb | 250 |
Usage
import wat from 'watr'
// compile text to binary
const buffer = wat(`(func
(export "double") (param f64) (result f64)
(f64.mul (local.get 0) (f64.const 2))
)`)
// create instance
const module = new WebAssembly.Module(buffer)
const instance = new WebAssembly.Instance(module)
// use API
const {double} = instance.exports
double(108) // 216
Compiler
WAT tree can be compiled directly, bypassing text parsing:
import { compile } from 'watr'
const buffer = compile([
'func', ['export', '"double"'], ['param', 'f64'], ['result', 'f64'],
['f64.mul', ['local.get', 0], ['f64.const', 2]]
])
const module = new WebAssembly.Module(buffer)
const instance = new WebAssembly.Instance(module)
const {double} = instance.exports
double(108) // 216
Limitations
Ambiguous syntax is prohibited in favor of explicit lispy structure.
Each instruction must have prefix signature with parenthesized immediates and arguments.
It may be supported, but discouraged.
(func (result i32)
i32.const 1 ;; ✘ stacked arguments
drop
i32.const 0
i32.load offset=0 align=4 ;; ✘ ungrouped immediates
)
(func (result i32)
(drop (i32.const 1)) ;; ✔ nested arguments
(i32.load offset=0 align=4 (i32.const 0)) ;; ✔ grouped immediates
)
(local.get 0)
if (result i32) ;; ✘ inline instruction
(i32.const 1)
end
(local.get 0) ;; ✘ stacked argument
(if (result i32)
(i32.const 1)
)
(if (result i32) (local.get 0) ;; ✔ explicit signature
(i32.const 1)
)
(f32.const 0x1.fffffep+127) ;; ✘ floating HEX (not supported)
(global.set $pc (;(i32.const <new-pc>);)) ✘ default arguments must be explicit
It may also miss some edge cases and nice error messages. For good REPL experience better use wabt.