Writing my first Interpreter

Thursday, Sep 17, 2020

Github Repository : My first Interpreter

It was around late 2019 when I decided to learn “golang”. The language was old but lately getting a lot of traction with many firms adopting it and talking about replacing Java. A lot many distributed systems products such as Docker, Kubernetes, etcd, Boltdb, Cockroachdb have been developed in the language and all this got my attention and gave me enough motivation to learn it. It was no doubt I liked the concurreny model and no sharing of data between two go-routines it made life a lot easier.

While learning through the syntax and conditionals I was curios to understand what happens under the hood in the language and with the language being open-source I started to try and make sense of the source code. I got a few books online to understand the grammar and process of writing a language, I found the best way I could go about it, was to write a language of my own.

And, so I started my journey to the daunting task of writing an Interpreter. It seemed I might have bitten off more than I could chew. But I was determined to learn and finish what I started. I used the TDD approach writing my tests always before the actual language code. I started slowly writing bits and pieces of the language, first I started with the Lexer that breaks the input into individual tokens. I also quickly implemented the REPL (Read Eval Print Loop) to get quick feedback.

Writing the REPL early on helped to keep the motivation high and have my mind on the final prize. I could fire up the language and quick check the input being broken down to Tokens, this gave that rare statisfaction that usually all developers crave for in a project well written.

Next, I started with Parser, here I luckliy came across an amazing book by Thorsten Ball. Writing an Interpreter in Go. The way it explains Pratt Parser and implements it is next level. The book breaks down the pretty hard topic in small chunks and simplifies key areas to get the point across with minimum use of Jargons.

I implemented the Pratt Parser, that would take the Tokens as input and parse them into an Abstract Syntax Tree. Next was an Evaluator that would evaluate the AST after converting the Tree into an internal Object system. The Object system was to hold the references to variables within the current scope of functions and the main REPL loop.

The language currently is still a toy language and far from Turing complete. The Lexer, Parser and Evaluator are not the most efficient on the planet but that being said this was my first attempt at something like this and I can definetly say this is a language that I am proud of.

It was humbling experience to peek under the hood and attempting to write a scaled down version of the same. I learned and enjoyed a lot but this being a 7 months project it tested my perseverence to the limit I am glad I stuck to it and saw it through.