Overview
For the past few weeks (although I started the book months ago), I have focused on finishing Writing an Interpreter in Go by Thorsten Ball. I've tracked my gradual progress in this github repository, if you'd like to see the code.
Now that I've finished the book, I have successfully written a programming language (called Monkey) supporting mathematical expressions, variables, functions, conditionals, returns, and higher order functions and closures! Very cool!
Below, I've written a basic summary and review of the book, capturing my reflections on the experience of completing this book. Below that, I also have added some notes about potential future improvements that Thorsten left up to the reader (me, in this case) to implement in the future. I will likely try to implement some of them in the future, but if I forget to update this post, I'll likely have pushed my changes to GitHub, at least.
Book Summary & Review
The book is split into four chapters: Lexing, Parsing, Evaluation, and Extending the Interpreter.
Our programming language uses a REPL. That is, a "Read Eval Print Loop". We will read the input (the source code), evaluate the input, print the output, and loop with more input.
To construct this REPL, we use chapters 1 and 2 to read the input and chapter 3 to evaluate it. With our programming language, we use our lexer made in chapter 1 to convert the source code into tokens that we then pass on to our parser in chapter 2. Taking in these tokens, our parser creates an abstract syntax tree. If you've taken a data structures class that covers trees, this will be very familiar to you! Using that abstract syntax tree, we are then able to traverse the tree and evaluate what the output of our input should be, which is exactly what we do in chapter 3. After that, everything is in place for us to add just a few more features to make Monkey look more like the other programming languages we're used to. So, in chapter 4, we add strings, hashmaps, arrays, built-in functions, and get a great overview of everything we built in the first three chapters.
I thoroughly enjoyed this book, and I think it is a great and accessible resource for learning more about interpreters and programming languages. It does cover some technical topics, like parsing, but avoids getting bogged down in the details more than is necessary for implementing any individual component of the interpreter. If you're looking for an extremely technical resource on specific parsing methods, garbage collection, or just in time compilers, this isn't the book for you. Instead, this is a practical resource that allows you to write a programming language and gives you avenues to explore in the future. I enjoyed it a lot, and am excited to explore more about interpreters while using the basics I learned here as I go!
4.5/5
Potential Future Improvements
- Adding support for postfix expressions (like i++, i--)
- Adding line and column numbers to the lexer in order to create improved error messaging
- Adding additional string features, like string comparisons
- Adding more built-in functions, aside from the ones already provided in the book
- Adding separate chaining or open addressing to handle hash collisions
- Optimizing hashing performance
- Finishing Thorsten's follow-up book, Writing a Compiler in Go, which is an extension of this book