b2KIT

WAT / WASM Text Format Playground

Write WebAssembly Text Format (WAT), compile to WASM, and execute with interactive I/O.

Tested tool guide Tested browser tools Checked August 16, 2026

What WAT / WASM Text Format Playground does, with a checked example

Write WebAssembly Text Format (WAT) in an editor pane, compile it to the .wasm binary format entirely in the browser, and call the module's exported functions with typed inputs to see results. The tool validates as it compiles, so syntax and type errors surface with a line number rather than as a mysterious failure at run time. The surprise for most newcomers: WAT is stack-based and there are no strings. Every value crossing the boundary is a number; text and arrays exist only as bytes in linear memory. And a module without any (export ...) compiles fine but does nothing.

Worked example

A concrete input and expected output from the current implementation.

Input

(module
  (func (export "fact") (param $n i32) (result i32)
    (local $acc i32)
    (local.set $acc (i32.const 1))
    (block $done
      (loop $again
        (br_if $done (i32.eqz (local.get $n)))
        (local.set $acc (i32.mul (local.get $acc) (local.get $n)))
        (local.set $n (i32.sub (local.get $n) (i32.const 1)))
        (br $again)))
    (local.get $acc)))
Then call fact(5) in the run panel.

Expected output

Module compiles and instantiates; fact(5) returns 120.

Each pass through the loop multiplies the accumulator by the current n, then decrements n, until n reaches zero: 1 x 5 x 4 x 3 x 2 x 1 = 120. The loop and br_if are the entire logic, so if they targeted the wrong label the module would still compile and run, just with a different answer.

How the result is produced

1

From text to a running module

The editor content is tokenized and parsed as S-expressions, then type-checked: every instruction must consume and produce stack values of the declared types, branch labels must exist, and exports must name real functions. Errors are reported with the offending line and column. When the checks pass, the module is encoded into the .wasm binary format, then validated and instantiated by the browser's WebAssembly engine before any of your calls execute.

2

The call boundary

Only functions marked (export) are callable from the run panel. Typed arguments are parsed to the declared parameter types (i32, i64, f32, f64), passed into the module, and the returned value comes back as a JavaScript number. WebAssembly has no strings, so text travels only as bytes in linear memory, and values are interpreted as signed, which is why large bit patterns display as negative numbers.

Good uses

  • Teaching or learning the instruction set: write a snippet, hit compile, and get line-level feedback on what is and is not valid WAT, without installing wabt or a toolchain.
  • Prototyping a hot loop or kernel before porting it: confirm the semantics of wrapping arithmetic, i64 operations, or memory access in an isolated module, then copy the verified WAT into a real build.
  • Isolating a suspected WebAssembly bug: paste the WAT for just the function that misbehaves, call it with boundary inputs, and determine whether the module or the surrounding JavaScript is at fault.

Limits and checks

  • A clean compile is not a correct program. Validation checks types and structure, not behavior: the module can still trap at run time (division by zero, out-of-bounds memory access), loop forever, or return values that only make sense after accounting for i32 wrapping.
  • Read results as signed. An i32 output whose high bit is set displays as a negative number, so a bit pattern like 0xFFFFFFFF shows as -1. f32 and f64 values come back through JavaScript number formatting, which can round or print values like 1e+21.
  • A call that never returns blocks everything. WebAssembly functions execute synchronously and cannot be interrupted from JavaScript, so an infinite loop in your module hangs the run panel (and the page, if it runs on the main thread) until the tab is closed.

Common questions

Why does i32.add of 2147483647 and 1 give -2147483648?

Because i32 arithmetic is modulo 2^32. 2147483647 is 0x7FFFFFFF; adding 1 produces 0x80000000, which interpreted as a signed 32-bit integer is -2147483648. The tool is reporting the bits exactly - nothing overflowed into a trap. Switch to i64, or reinterpret as unsigned, when you need larger positive values.

Can I print text or return a string from my module?

No. WebAssembly has no string type, so a function described as returning text is really returning a number - a pointer or length into linear memory. To display text you must write UTF-8 bytes into a memory export and decode them, which requires a host-side helper or a memory view. If the playground exposes neither, treat string-like results as addresses.

References and verification

The example and behavioral notes were checked against the browser implementation. Standards and primary references below define the relevant format, formula, or platform behavior.

Related Tools