Skip to main content

Reed language guide

Reed is a small typed language for writing a single WebAssembly module. It stays close to the machine: value types, structured control, GC heap types, and low-level instructions all map visibly to the WAT that comes out.

This guide walks through the language by building and reading small modules. If you need the exact grammar or validity rule, use the authoritative specification. If you want to know what is missing or still risky, start with Limitations and rough edges.

The shape of a module

A source file describes one WebAssembly module. Declarations add functions, types, globals, tables, memories, imports, exports, and an optional start function.

global Counter: mut i32 = 0;

func increment() -> i32 {
  Counter = Counter + 1;
  return Counter;
}

export func increment as "increment";

The ABI name is explicit. The source name and the exported WebAssembly name can match, but they do not have to.

Trying it

Save the example above as counter.reed and compile it:

$ reedc build counter.reed
reedc: catalog reedc-core-gc-eh-simd-threads-1 -> counter.wat

counter.wat is readable WebAssembly Text, with comments tracing each instruction back to the Reed source that produced it:

;; reedc catalog: reedc-core-gc-eh-simd-threads-1
(module
;; func increment(...)
(func $increment
(result i32)
;; Counter = Counter + 1;
(global.set $Counter (i32.add (global.get $Counter) (i32.const 1)))
;; return Counter;
(return (global.get $Counter)))
;; global Counter: ... = ...;
(global $Counter (mut i32) (i32.const 0))
;; export func increment as "increment";
(export "increment" (func $increment)))

Or skip the install and try it here. Edit the source below and the WAT updates as you type, using the same compiler compiled to WebAssembly:

Loading playground…

The playground has more examples to load, covering GC types, control flow, and raw wasm.* operations. See command-line interface for reedc check (diagnostics without writing a file) and reedc lsp (editor integration).

What Reed targets

Reed's current target includes:

  • WebAssembly core instructions and numeric value types.
  • Multi-value functions and structured blocks.
  • Reference types and WebAssembly GC structs, arrays, i31, casts, and tests.
  • Exception handling in full: tag, throw, and try/catch with rethrow.
  • Fixed-width and relaxed SIMD, through the v128 type and the lane-wise operations.
  • Atomics with shared memory, and 64-bit memories.
  • Annotations: custom sections, and @likely/@unlikely branch hints.
  • Typed low-level wasm.<opcode> operations for the selected instruction catalog.

Runtime strings (stringref), stack switching, and half-precision floats are not implemented. Tail calls are an output flag, not a source construct. See Limitations for the full list.

The libraries

Two, and they are different mechanisms rather than two halves of one:

  • The core library is in every program with no import. It is 42 @inline methods giving a name to WebAssembly instructions ordinary syntax cannot spell — clz, div_u, sqrt. A call costs exactly the instruction it wraps, and nothing is emitted.
  • The standard library is opt-in. Ten modules of ordinary Reed — integer math, bit manipulation, ASCII, strings, growable lists, sorting, hash maps and sets, seeded randomness — imported with a std: path:
use std.str.*;
use std.sort.{sort};

Only the functions your program can reach are emitted. If you are looking for gcd, sort, or a string type, it is the standard library you want.

Where to go next

For quick lookup:

For learning one feature at a time:

For complete modules you can edit and run:

  • Program examples — every worked example on one page, each one compiled and executed by the test suite.
  • Tooling and generated output — the CLI, the language server, the editor grammars, and what the emitted WAT looks like.