The Tessera Book

The Tessera Book

Welcome. This book teaches Tessera, a small compiled language built around one idea: code can only touch the outside world through capabilities it was handed. There is no global print, no open, no http.get, no clock you can reach from anywhere. A program starts with a single value, root, which holds every authority the program was given, and it passes narrower pieces of that authority to the functions that need them.

That one rule has a pleasant consequence. A function's parameter types tell you everything it can do. A function that takes a Stdout can print and nothing else. A function that takes a Net limited to one host can talk to that host and nothing else. A function that takes no capability at all can only compute: it cannot read your files, open a socket or look at the time, however deep its call tree goes. The compiler knows this too, and it will show it to you.

In Roman times a tessera was a small tile or token, and a tessera hospitalis was one handed between a host and a guest: whoever brought it back proved the right to hospitality. The logo of this book is such a tile with a T cut into it, and a capability in Tessera works much the same way: you can only do what you were handed the token for.

Who this book is for

The book assumes you have written programs before, in any language, and know what a variable, a function and a loop are. It does not assume you know anything about capabilities, type systems or concurrency. Each chapter introduces a few ideas and uses them right away in small programs you can run.

How to use this book

Read it in order the first time. Chapters 1 to 6 cover the core language, chapters 7 to 11 the things you need for real programs (modules, errors, collections, generics and tests), and chapters 12 to 15 the parts that make Tessera what it is: capabilities in depth, concurrency, talking to the network and the file system, and calling C. Chapter 16 puts it all together in a small web service. The appendices are for looking things up.

Every program in this book is real. Each listing lives in the book's repository under examples/, and the build that produces these pages type-checks every one, checks its formatting, runs it, and compares what it prints with the output you see on the page. When a listing is there to show a compiler error, it is marked as one, and the error shown is the one the compiler really gives.

fn main(root: Root) {
    root.stdout.print("Hello, world!")
}
Listing -1: A whole Tessera program examples/ch01-01-hello/main.tsr

Output from a terminal looks like this. Lines starting with $ are commands; everything else is what they printed:

$ tessera run main.tsr
Hello, world!

What Tessera is like

If you have used a language with type inference, sum types and pattern matching, most of Tessera's syntax will feel familiar. A few things are different and worth knowing up front:

  • Values, not references. Assigning a list or a struct copies it, as far as your program can tell. Two variables never see each other's changes. Chapter 4 explains why this is cheap.
  • No null. A value that might be missing has the type Option[T], and the compiler makes you deal with the missing case.
  • Errors are values. Functions that can fail return a Result, and the ? operator passes the failure up. A panic is for bugs.
  • Concurrency is structured. Tasks live inside a group block and are finished when the block ends. What they print comes out in a predictable order.
  • Two backends, one behaviour. tessera run interprets a program; tessera build compiles it to native code through C. Both give the same results, down to the order of output and the way integers wrap.

Let's get started.