The WebAssembly Text Format (WAT)
4.1 S-Expressions and Linear Syntax
Comments: ;; line and (; block ;). Identifiers start with $ and are symbolic names for indices (stripped in the binary unless the name section is kept).
(module
;; Linear (stack) style
(func $sq_linear (param $x i32) (result i32)
local.get $x
local.get $x
i32.mul)
;; Folded (S-expression) style: same semantics, more readable
(func $sq_folded (param $x i32) (result i32)
(i32.mul (local.get $x) (local.get $x)))
(export "sq" (func $sq_folded)))4.2 Index Spaces
Every entity kind (types, functions, tables, memories, globals, locals, labels, elements, data, tags) has its own index space. Imports come first in their index space.
(module
(import "env" "log" (func $log (param i32))) ;; function index 0
(func $main (call $log (i32.const 42))) ;; function index 1
(start $main))4.3 Abbreviations
(func (export "f") (param i32 i32) (result i32) ...) ;; inline export, unnamed params
(memory (export "memory") 1) ;; 1 page = 64 KiB
(memory (data "Hello")) ;; inline data
(global $counter (mut i32) (i32.const 0))
(type $binop (func (param i32 i32) (result i32)))
(func $add (type $binop) (i32.add (local.get 0) (local.get 1)))4.4 A Complete Example: Factorial
(module
(func $fac (export "fac") (param $n i64) (result i64)
(if (result i64) (i64.le_s (local.get $n) (i64.const 1))
(then (i64.const 1))
(else
(i64.mul
(local.get $n)
(call $fac (i64.sub (local.get $n) (i64.const 1))))))))const { instance } = await WebAssembly.instantiate(bytes);
console.log(instance.exports.fac(20n)); // i64 maps to BigInt in JS → 2432902008176640000n