Skip to content
Menu
Compiles to WebAssembly

Small. Strict. Inferred.

Bert is a small, strict, functional language with inferred types. It compiles straight to WebAssembly.

shapes.bertno type annotations
# Shapes are plain tagged values. No declarations.
area = (shape) -> match shape {
  Circle(r) -> 3.14159 * r * r
  Rect(w, h) -> w * h
}

total = (shapes) ->
  List.foldl(shapes, 0.0, \(sum, s) -> sum + area(s))
Inferred
area : ([Circle(Float) | Rect(Float, Float)]) -> Float
total : (List([Circle(Float) | Rect(Float, Float)])) -> Float

Less to write, less to go wrong.

Bert infers every type, treats failure as ordinary data, and compiles to one portable artifact.

Errors are data

A failing call returns a Result. The trailing ? unwraps it or returns the error, and every error tag adds itself to the type.

parseAge = (text) -> {
  n = Int.fromString(text)?
  if n < 0
    then Err(Negative(n))
    else Ok(n)
}
Inferred
parseAge : (String) -> [Err([InvalidInt | Negative(Int) | a]) | Ok(Int) | b]

Structural types, no ceremony

Records and variants are plain values. A function that reads a field accepts any record that has it.

# Any record with a name field.
greet = (user) -> user.name

ada = greet({ name: "Ada", age: 36 })
grace = greet({ name: "Grace" })
Inferred
greet : ({ name: a | b }) -> a

One compiler, two targets

Build a core WebAssembly module for WASI preview1 or your own host, or a WebAssembly component for WASI 0.2.

# Core module
$ bert build App.bert --output app.wasm

# Component: set [component] in bert.toml
$ bert build App.bert --output app.component.wasm

Learn by building.

A first program, then two tutorials that build a command-line tool and a web server.

Write your first Bert program.

Open the playground, change a few lines, and see the result. Nothing to install.