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!")
}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
groupblock and are finished when the block ends. What they print comes out in a predictable order. - Two backends, one behaviour.
tessera runinterprets a program;tessera buildcompiles 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.