Book 1 · 2016 · You are here
Writing An Interpreter In Go
Build an interpreter for the Monkey programming language from scratch: lexer, Pratt parser, AST, a tree-walking evaluator and a REPL.
Book 1 of the Monkey books
In this book we will create a programming language together.
We'll start with 0 lines of code and end up with a fully working interpreter for the Monkey programming language.
Step by step. From tokens to output. All code shown and included. Fully tested.
Compilers was the most surprisingly useful university course I ever took. Learning to write a parser and runtime for a toy language helps take away a lot of "magic" in various parts of computer science. I recommend any engineer who isn't familiar with lexers, parsers, and evaluators to read Thorsten's book.
Mitchell Hashimoto
@mitchellh
The series
This book has a sequel. In Writing A Compiler In Go we take the interpreter we build here and turn it into a bytecode compiler and a virtual machine.
Book 1 · 2016 · You are here
Build an interpreter for the Monkey programming language from scratch: lexer, Pratt parser, AST, a tree-walking evaluator and a REPL.
Book 2 · 2018
The sequel: turn Monkey into a bytecode compiler and a stack-based virtual machine that runs it, closures and all, 3x faster.
Visit compilerbook.com →Get both books as a bundle. Writing An Interpreter In Go and Writing A Compiler In Go in ePub, Mobi, PDF and HTML, plus all the code, for a reduced price.
Buy the bundle $50What you'll learn
This is the book I wanted to have a year ago. This is the book I couldn’t find. I wrote this book for you and me.
So why should you buy it? What’s different about it, compared to other interpreter or compiler literature?
“If you don’t know how compilers work, then you don’t know how computers work. If you’re not 100% sure whether you know how compilers work, then you don’t know how they work.”
“Start by writing an interpreter with me!”
Who it's for
The language
In this book we’ll create an interpreter for the Monkey programming language. Monkey is a language especially designed for this book. We will bring it to life by implementing its interpreter.
Monkey looks like this:
// Bind values to names with let-statements
let version = 1;
let name = "Monkey programming language";
let myArray = [1, 2, 3, 4, 5];
let coolBooleanLiteral = true;
// Use expressions to produce values
let awesomeValue = (10 / 2) * 5 + 30;
let arrayWithValues = [1 + 1, 2 * 2, 3];
Monkey also supports function literals and we can use them to bind a function to a name:
// Define a `fibonacci` function
let fibonacci = fn(x) {
if (x == 0) {
0 // Monkey supports implicit returning of values
} else {
if (x == 1) {
return 1; // ... and explicit return statements
} else {
fibonacci(x - 1) + fibonacci(x - 2); // Recursion! Yay!
}
}
};
The data types we’re going to support in this book are booleans, strings, hashes, integers and arrays. We can combine them!
// Here is an array containing two hashes, that use strings as keys and integers
// and strings as values
let people = [{"name": "Anna", "age": 24}, {"name": "Bob", "age": 99}];
// Getting elements out of the data types is also supported.
// Here is how we can access array elements by using index expressions:
fibonacci(myArray[4]);
// => 5
// We can also access hash elements with index expressions:
let getName = fn(person) { person["name"]; };
// And here we access array elements and call a function with the element as
// argument:
getName(people[0]); // => "Anna"
getName(people[1]); // => "Bob"
That’s not all though. Monkey has a few tricks up its sleeve. In Monkey functions are first-class citizens, they are treated like any other value. Thus we can use higher-order functions and pass functions around as values:
// Define the higher-order function `map`, that calls the given function `f`
// on each element in `arr` and returns an array of the produced values.
let map = fn(arr, f) {
let iter = fn(arr, accumulated) {
if (len(arr) == 0) {
accumulated
} else {
iter(rest(arr), push(accumulated, f(first(arr))));
}
};
iter(arr, []);
};
// Now let's take the `people` array and the `getName` function from above and
// use them with `map`.
map(people, getName); // => ["Anna", "Bob"]
And, of course, Monkey also supports closures:
// newGreeter returns a new function, that greets a `name` with the given
// `greeting`.
let newGreeter = fn(greeting) {
// `puts` is a built-in function we add to the interpreter
return fn(name) { puts(greeting + " " + name); }
};
// `hello` is a greeter function that says "Hello"
let hello = newGreeter("Hello");
// Calling it outputs the greeting:
hello("dear, future Reader!"); // => Hello dear, future Reader!
Yes! All of this works with the interpreter we build in the book!
So, to summarize: Monkey has a C-like syntax, supports variable bindings, prefix and infix operators, has first-class and higher-order functions, can handle closures with ease and has integers, booleans, arrays and hashes built-in.
And Monkey has taken on a life of its own: readers have built nearly 100 Monkey implementations in more than 25 languages, from Rust and TypeScript to Zig, OCaml and Haskell.
Reviews
Rated 4.6 ★ on Amazon and Goodreads, and recommended on Hacker News year after year.
I wrote "Crafting Interpreters" and read and very much enjoyed Thorsten's interpreters book. … Both are written in an informal friendly style and focus on working code. … His will get you to a working interpreter with less prose to wade through.
This book is excellent. It is well written, and the code extracts compile and work. That is not something I can say about all the computer books I have had over the years.
I am an experienced developer who has read many computer books, including ones on compilers and interpreters. This one is probably at the top of my list of well written computer programming books.
Thorsten has a wonderful gift — as you read his books, you'll feel as though you've discovered compilers, all on your own! As a self-taught engineer without a CS degree, I found myself led on a journey of learning, driven by the nuggets of 'why' that Thorsten shares alongside code.
I've recommended these books to many, and I won't hesitate to continue. Compilers, interpreters and programming languages may seem esoteric, but if you look closely, they're everywhere. The Monkey language is my go-to project whenever I learn a new programming language. There's no better way to take a new language through its paces!
Lauren Tan
@potetotes
This is a very polished pair of books that together give a steady path to follow for learning some of the real techniques that are used to implement programming languages. They're both well above average for their depth, technical clarity, and accessibility. I've been recommending them to everyone I work with who wants to get involved in compilers.
Chris Seaton
@ChrisGSeaton
I've read many books and web articles on writing compilers and interpreters and this is one of the most accessible yet. … The book contains a lot of simple elegant code that is a joy to read.
I would love it if the author writes a second volume focused on optimization or compiling down to native instruction.
I can't recommend this book more highly. Not just as an example of interpreter construction or engineering in Go, but as a perfect example of technical writing.
Great book. I loved it because everything is built by hand, so you get to think about all the details, and it does so in a gradual way, which is didactic. The implementation itself is also nice and simple 🙌
Xavier Noria
@fxn
Perhaps the most approachable literature I have seen on the topic, everything is explained clearly, in detail, and without skimping on specifics - but it's not at all overwhelming.
This is a great book. It's clear, concise and packed full of learnings.
The result is impressive, and I am somewhat astonished by just how much content is actually in here, and how well written said content is.
The book definitely delivers on the promise - it builds the interpreter from the ground up, from lexer to parser to evaluator, with tests written first to give the reader an immediate view of what's coming.
I especially liked the fact that the author doesn't cut corners on writing test harness for the code, and doesn't abuse the "<such and such> is left as an exercise for the reader" phrase - that alone is an indicator of thoroughness and no-nonsense approach to writing.
Amazing book! Besides satisfying my curiosity with clear writing and code examples, the book inspired me to apply those skills to a new http testing tool I’m working on.
Felix Geisendörfer
@felixge
I really enjoyed the modern, practical approach of this book. Diving into the world of interpreters, by getting your hands dirty right from the beginning.
Christian Bäuerlein
@fabrik42
This book demystifies and makes the topic of interpreters approachable and fun. Don't be surprised if you become a better Go programmer after working your way through it.
Johnny Boursiquot
@jboursiquot
Great writing and explanations. The practical focus of the book kept me coding for a week straight. Definitely the best book to get into the magical world of compilers and interpreters.
We use parsers and interpreters on a daily basis, just think of JavaScript and JSON. This book not only helped me to better understand how they work but will come in handy the next time I have to implement a parser for an obscure data format.
Robin Mehner
@rmehner
This book clearly, and elegantly explains the different pieces needed to make a language. From lexing and parsing to actually executing the code, this book does a great job explaining to the reader the purpose of each element and how they interact.
I loved this book and it remains one of my favorite #golang books to this day.
Brian Downs
@bdowns328
I only wish this book was available ten years ago! At the time I was using Appel's Java book and trying wade through the dragon book too. It's so refreshing to have a TDD-based tutorial to learn the concepts in a language you might reasonably use to build an interpreter.
Robert Gravina
@robertgravina
It has been one of the funnest experiences in my programming career. I recommended your books to all my friends in the industry. I recently finished 'Writing An Interpreter In Go' and yesterday I purchased 'Writing A Compiler In Go'. Once again thank you! I was blind and now I can see, thanks to you!
This book is not only educational, but the code quality is incredible, which allows the reader to move seamlessly from chapter to chapter without the need to scratch their head over what the code means or how it works. It is cleanly separated, well optimized, highly readable, and very precise in its functionality. Because of this, it provides an excellent example for both novices and veterans of the Go programming language, and will serve readers beyond a purely intellectual understanding of programming language design and functionality; the code used in the book will also provide a solid foundation in Go programming that can be practically applied right away. This balance is tough to achieve, and made the book a joy to read.
Aaron Hnatiw
@TheHackerDev
I was completely hooked by your book on writing an interpreter and read it in 3 days. It might be the best book on programming I've ever read, and I read a lot of them. I love how all of the concepts are explained simply through very readable code and I love how the product turned out so real and useful. I wish more books were written in this style and I look forward to diving into the sequel!
Ludvig Gislason
@ludviggislason
Thorsten took a topic that is usually very dry and CS heavy and made it accessible and easy to understand. After reading this book I felt confident enough to write Plush, the templating language I’ve always wanted in Go! If you have yet to read Thorsten's book, I can't recommend it enough. Please go and buy it!
Mark Bates
@markbates
The best thing to do on a maternity leave when the baby is sleeping? Write an interpreter based on Thorsten Ball's book Writing An Interpreter In Go. I had so much fun! Now off to writing a compiler!
Alena Varkockova
@alenkacz
Thorsten's writing style is fun and easy to understand with detailed explanations and even better code. Even if you've written an interpreter before, this book is a great refresher. I picked it up as a project to learn Rust, translating the example Go code into Rust as I read through. Lexers, parsers, and interpreters are such a fundamental part of CS, these skills are valuable to more than just programmers implementing programming languages. As a project for picking up a new language, this book is perfect because it only requires the standard library and has extensive test driven development, which means you get quick feedback as you go along. I highly recommend it for programmers wanting to learn more about lexers, parsers, and interpreters or Go programmers picking up a new language looking for a project to learn through.
Paul Dix
@pauldix
It's been the most fun I've had in years.
…the Interpreter Book and Compiler Book, both written for Go as the implementation language. They were all a huge help for me learning the ropes initially.
I went over "Writing an Interpreter in Go" and "Writing a Compiler in Go" but instead of doing it in Go, I did it in C. … I really recommend Writing an Interpreter/Compiler in Go.
I found them exceedingly approachable and great in any language (I did mine in Typescript).
Writing an Interpreter in Go / Writing a Compiler in Go, the two part series by Thorsten Ball, was what I really cut my teeth on.
Absolutely best books I've ever read on the subject.
I cannot recommend Thorsten Ball's books highly enough. They're really fantastic, step-by-step tutorials, and you certainly don't need a CS degree to understand what he's doing.
If you want to dive into compiler/interpreters but do not want to go straight into the computer science of it I wholeheartedly recommend: https://compilerbook.com and https://interpreterbook.com
I really love Writing An Interpreter In Go. The book presents the material in a smooth and clear progression and anticipates the questions the reader may have.
I am a 66-year-old retired programmer. I just finished this month of reading and coding along with reading your remarkable book, which gave me moments of real joy.
I have gone through the dragon book before and have been working on compilers optimisations for a while. But Thorsten's book made me comfortable in compiler frontend.
Read this if you're bored by the first few chapters of literally ANY compiler book in existence and just want to write a working parser you actually understand.
By far, my favourite technical book I've ever read.
A simply outstanding book on Programming Language implementation. Thorsten Ball has done an amazing job writing a book with clear explanations, easy to follow code, code that works
I learned so much from working through this book, and not just about interpreters - about dealing with complexity, writing proper unit tests, writing a REPL, etc.
…this strikes the perfect balance between a theory laden dissertation and a trivial example. It's clear, concise and hands on.
This is probably the 9th book about compilers I bought and read in the last two years... And I loved it.
…it is a book about writing an interpreter in Go, exactly as the title says, and I love it.
The writing is very accessible, and the Pratt Parser implemented is thoughtfully constructed.
Also, I really like the fact that the interpreter is built TDD-style. That makes it easy to spot errors early, and also to extend the implementation painlessly.
Thorsten illustrates some of the joy and elegance of programming small clever things, before we got bogged down in frameworks and enterprise jargon.
Both books are wonderfully written. Code in both book work as advertised.
Ever since I left school I wanted to someday write a compiler. I did it! :-)
Get the book
$29
$50
$58
$39
All the code Runnable, organized by chapter, MIT licensed and including the complete test suite.
Free updates eBook buyers get every update for the lifetime of that edition of the book.
Money-back guarantee I want you to enjoy this book. If you, for any reason, are not happy with it, just send me an email. You'll keep what you bought and get your money back.
Current version: 1.7. Last updated 7 May 2020. See the changelog.
FAQ
Absolutely not! On the contrary, this book was written for you!
Yes! I wrote the book with the aim to keep the code as easy to understand as possible. If you are experienced in other programming languages you should be able to understand it. Take a look at the free excerpt: that's as advanced as the Go code gets.
Yes. The code comes with go.mod files, uses only the standard library and its complete test suite passes with current Go releases.
I'm sorry to say it, but no, I cannot bundle eBooks with paperbacks. It's not that I don't want to (I do!) but I can't. The eBooks are sold and distributed through LemonSqueezy, where I have a lot of influence on the process, but the paperback editions are being printed, sold and shipped by Amazon and I don't have many options there. I can't tell Amazon to bundle digital files with the paperback. Sorry!
Take a look at the changelog to see whether I've already fixed it. If I haven't or you're not sure I have, please send me an email to me @ thorstenball.com. I really appreciate it!
Well, I always thought I could use the "Golang" somewhere on the landingpage, maybe in the FAQ or something.
Sure, just send me a picture! I'm always fascinated by new places and love seeing where people live, so here's my proposal.
You go outside, take a picture of where you live and send it to me to me @ thorstenball.com. Tell me what you feel comfortable paying for the book(s) and we'll make that happen.
Free bonus chapter
More than half a year after publishing Writing An Interpreter In Go I decided to write another chapter. An additional chapter that’s available to everyone: free to read online or to download as an eBook.
It’s called The Lost Chapter: A Macro System For Monkey and can be thought of as the fifth chapter for Writing An Interpreter In Go. It builds directly upon the previous four and extends the Monkey interpreter as it stands at the end of the book.
In the chapter we add a fully-working Lisp-style macro system to Monkey, that’s close to the way Elixir’s macro system works. It looks like this:
let unless = macro(condition, consequence, alternative) {
quote(if (!(unquote(condition))) {
unquote(consequence);
} else {
unquote(alternative);
});
};
unless(10 > 5, puts("not greater"), puts("greater"));
// outputs only: "greater"
Building your own programming language is likely not something you do in your day job. But adding a fully working macro system? Well, that’s not just unlikely, but outright bizarre and, oh, so much fun! Macros are code that writes code. Can you imagine how much fun it is to write code that allows us to write code that writes code? Exactly!