Despite using them every day, most software engineers know little about how programming languages are designed and implemented. For many, their only experience with that corner of computer science was a terrifying "compilers" class that they suffered through in undergrad and tried to blot from their memory as soon as they had scribbled their last NFA to DFA conversion on the final exam.
That fearsome reputation belies a field that is rich with useful techniques and not so difficult as some of its practitioners might have you believe. A better understanding of how programming languages are built will make you a stronger software engineer and teach you concepts and data structures you'll use the rest of your coding days. You might even have fun.
This book teaches you everything you need to know to implement a full-featured, efficient scripting language. You’ll learn both high-level concepts around parsing and semantics and gritty details like bytecode representation and garbage collection. Your brain will light up with new ideas, and your hands will get dirty and calloused.
Starting from main(), you will build a language that features rich syntax, dynamic typing, garbage collection, lexical scope, first-class functions, closures, classes, and inheritance. All packed into a few thousand lines of clean, fast code that you thoroughly understand because you wrote each one yourself.
Robert Nystrom has programmed professionally for twenty years, about half of which is in games. During his eight years at Electronic Arts, he worked on behemoths like Madden and smaller titles like Henry Hatsworth in the Puzzling Adventure. He's shipped games on the PC, GameCube, PS2, XBox, X360, and DS, but is most proud of the tools and shared libraries he created for others to build on. He loves seeing usable, beautiful code magnify the creative ability of others.
Robert lives with his wife, two daughters, and two dogs in Seattle. If you have the misfortune of meeting him in person, he will invariably cook something for you.
Programming languages are something of a hobby of mine. Going as far back as undergrad, I’ve written a fair few interpreters and compilers over the years. I’ve never really gotten beyond a strong basic level, but I’ve always wanted to. Crafting Interpreters is a great book for exactly that.
The book essentially walks you through two styles of interpreter of the same language: just an AST walking style written in Java (the sort I’ve done a few times) and then a much more optimized one based on bytecode. There was something to learn on both sections though, since the the introduced language (lox) includes higher order functions and closures—certainly more interesting bits of languages to implement.
The latter really was the more interesting to me and really makes me want to go out and try building something more like that.
I think they biggest weakness of the book was in some ways also a strength: the author wrote all the code for the book before writing the prose—and then made sure that the book contained every line of the final interpreters. That does lead to some rather repetitive sections of adding very similar code to each new function, but so it goes.
Overall, well worth the read if you’re into programming languages, or really programming in general.
I’ve read hundreds of technical books over the last 40 years. Crafting Interpreters is an instant classic, and far more readable and fun than many of the classics.
Nystrom covers a lot of ground in this book, building two very different interpreters for Lox, a small dynamic language of his own design. He takes us through every line of jlox, a Java-based tree-walk interpreter, and of clox, a bytecode virtual machine written in C.
For the first implementation, jlox, he covers such topics as scanning, parsing expressions with recursive descent, evaluating expressions, control flow, functions and closures, classes, and inheritance.
Starting with an empty slate, Nystrom adds just enough code to implement the topic of each chapter, having a working albeit incomplete implementation of the interpreter by the end of the chapter. He adds new code as he goes, inserting an extra case into a switch here or writing a new function there, or replacing a few lines of an earlier implementation with something that’s just been explained. Knuth’s Literate Programming explains a finished implementation, broken into separate pieces for exposition. Nystrom’s continual, ever-evolving exposition is slower to get to the point, but it’s excellent pedagogy. I would be remiss if I didn’t mention the hundreds of hand-drawn illustrations, which add a quirky flavor to the tone of the book. He has a blog post on how he pulled this organization off and another on how he created a physical book from the text.
clox is a very different second implementation of a Lox interpreter. Instead of a slow interpreter walking an abstract syntax tree, he develops a stack-based virtual machine, compiles Lox into bytecode, and interprets the bytecode. He covers theory and practical considerations for creating a bytecode virtual machine, makes use of Pratt’s “top-down operator precedence parsing”, and implements closures and classes in C. In jlox, he used Java’s HashMap to manage identifiers and relied on Java’s garbage collection for memory management. For clox, he implements a hash table and a mark-and-sweep garbage collector. Although he has to cover similar topics (parsing, local variables, closures) each time, he finds a fresh perspective for the second implementation.
I read the entire book for free at https://craftinginterpreters.com/, but I liked it so much that I’ve ordered a physical copy. In fact, I actually read much of the book on the website in 2020, but life intervened and I didn’t finish it, so this month, I read it again from the start.
This book is not a textbook and you don’t get an exhaustive introduction to building interpreters, much less compilers. In the final year of my Computer Science degree at Trinity College Dublin in 1986–87, I studied the Dragon Book when the first edition was brand new. Crafting Interpreters is a lot more fun than the Dragon Book.
Kniha Crafting Interpreters od Roberta Nystroma, kterou jsem o víkendu dočetl, je dílem, které by se mohlo stát klasikou. Pro koho kniha je? Chtěli jste někdy vytvořit svůj vlastní programovací jazyk, nebo mít jednoduchý "embedovaný" skriptovací jazyk v aplikaci ? Moc ambiciózní a vy jste spokojeni se stávajícími jazyky? Hráli jste si třeba s C# Roslyn SDK, nebo jste použili C# generators a zhrozili jste se, jak amatérsky a nevzhledně vypadá - samozřejmě ne váš, ale kolegy 🙂 - generátor (no generátor, co jsem tak různě viděl, spíš spojování stringů na steroidech?) kódu? V knize Crafting Intepreters Robert Nystrom navrhne jazyk Lox. Lox je taková mini-Java (mini-C#, prostě jazyk s C like syntaxí), ale i přes nehezké přízvisko mini, které jsem použil v předchozí větě, Lox podporuje i OOP nebo closures - funkce, které zachytí proměnné ve svém okolí. V první části knihy autor nejprve napíše jednoduchý parser, lexer a interpreter Loxu v Javě. V druhé a pro mě zajímavější části autor napíše pro Lox (stack based) virtuální stroj v jazyce C včetně jednoduchého, ale plně funkčního garbage collectoru (jednovláknový, nekonkurenční, "stop the world"). A vytvoříte všechny instrukce pro virtuální stroj včetně vlastního disassembleru. A když když máte VM v C, portování Loxu na další HW platformy je hračka. Je poněkud tragické vidět vývojáře, kteří třeba intermediate language (IL) a VM v .NET považují za černé skříňky, kterým nemusejí vůbec rozumět. Do určité míry je to pravda, ale u každé netriviální aplikace potřebujete znát trochu více než syntaxi zvoleného programovacího jazyka a pár knihoven. A někdy ani nestačí, že jako firemní vývojářské eso rozpoznáte, kde je vyhledávací pole na StackOverflow, kam vložíte své zoufalé a bezradné skřeky. Na knize je skvělé, že obsahuje kompletní zdrojový kód. Ne útržky, ne odkazy na github. Veškerý výklad je prokládán kódem a je docela úleva číst knihu, ve které nejsou jen neoptimalizované fragmenty kódu, ale autor si dá práci, aby před vámi neskrýval žádné kroky, svůj kód před vámi vyladil a upozornil na typické chyby, kterých se dopustí asi každý, pokud píše třeba parser poprvé. Zvláštní cenu autor dostává za to, že nepoužívá trapné věty typu "tuto funkci už psát nebudeme, ponecháme ji jako cvičení pro bystré čtenáře." Moudří vědí, že jako cvičení pro čtenáře se často nechávají úlohy, které autor knihy nezvládne. Tento otravný a trapný trik asi autoři knih převzali od přednášejících mdlého ducha, kteří mají času dost, ale stejně ve stanoveném čase nestihnou vykoktat penzum znalostí, které si sami čerstvě osvojili den před svou přednáškou na konferenci, a s chutí přehazují povinnosti na posluchače. Také oceňuji, že kniha pro Kindle má všechny výpisy kódu čitelné. Pořád nejde o samozřejmost. Sami jste asi také narazili na odbornou eknihu, která byla formátována tak, že zdrojový kód nebo tabulky nebylo možné přečíst bez opičích chvatů (podržením prstu zvětším grafický objekt a skroluji tam a zpátky). Za tuhle knihu si autor zaslouží zaplatit, ale kdybyste byli i po mé nadšené recenzi na vážkách, nebo máte zrovna hluboko do kapsy, kniha je na webu zdarma.
This was recommended by a co-worker to whom I had made clear that I didn't quite understand the difference between bytecode and native code or exactly what WASM is. I can now say I do understand these things and that I could probably write a compiler if so compelled. Like so many things in computing, compilation appears to be a black art only the most hard-core geniuses could understand until you learn just a little bit about it.
So this book is great for demystification, but it's quite long and in need of an editor. It hasn't been published, after all, but do we really need a chapter about how to write a hash table? I soon stopped reading the asides and only made it about halfway through the C compiler. I don't think it makes sense to describe every line of code, although the book-as-code aspect of this project is pretty amazing. I found myself skimming through the chapters to understand what the new concept being presented was, then reading through the code, and going back to the text if there was anything I missed.
I'm glad I spent some time with this, but I suppose that high level programming languages are a layer of abstraction I'm happy to not dive too deeply into.
This is a great introduction to writing an interpreter. It start with the simple Java implementation, goes on to implement a virtual machine and then concludes by re-implementing everything in C with focus on performance. You will see chapters going through implementation of advanced features such as closures and OOP with inheritance.
In comparison to the famous Dragon Book this is a lot more practical reading. The book goes through every line of code, do not excluding anything. Despite of this, all of it is a pleasure to read. Author delivers material with humor and sprinkles every chapter with hand drawn illustrations which I adored.
Do not miss this book if you have any interest in programming language implementation.
(I skipped all the OOP chapters because I have no interest in that. There might be some hidden gems there, but I wouldn't know.)
I found the first part, which covered the tree-walking interpreter, to be quite confusing. The author chooses Java (it's a very popular language and OOP good) and /immediately/ begins to struggle with it. I'd guess most readers would've lost interest right at the point where we are starting to write "scripts" in Java to generate code for "Visitors" for out AST. If only there were languages better suited for writing interpreters!
The second part was far more interesting, probably because I'm not that familiar with compiling to bytecode (or compiling in general). Still, I would've found compiling to LLVM IR more immediately practical and generally useful, though it's likely too much for a reasonably sized book.
In the beginning, one might be fooled by a comforting design and illustrations. However, relatively fast it appeared to be a bit opinionated with a lot of questionable assumptions. Like, we are implementing parser in Java, or we focus too much on the language machinery rather than principles of implementation, or instead of being model-centristic we would rather code-generate the AST itself. Yeah, no-doubt, it is a massive effort of listing all the implementation steps in a comprehensible way, but it is hard to have some takeaways from any of it.
It's such a beautiful book. In essence it's a long code walk-through of interpreter of java-like language in the first part, and code walk-through of a simple VM & a compiler to byte-code in the second. Just a plain old fun and joy for geeks. Buy dead-tree version. It's beautiful. Don't even bother with kindle version it's broken beyond repair. The typography of this book was designed to be read from a paper.
This book isn't right for everyone. It requires fairly deep software development experience, and even deeper curiosity about the field. But as a hands-on way to learn how compilers and interpreters work, I actually can't think of how it could be improved.
The painstaking care of the author leaves you stunned. Not just in how perfectly the code is sequenced so that you have working code after every section, but also in the writing style, illustration, and even typography.
This book is the full realization of what a textbook should be.
A good overview of how to implement a bytecode interpreter; if you are willing to take on a dialect of LISP called Scheme, "The Structure and Interpretation of Computer Programs", might make a good companion.
Crafting Interpreters—hands down. It’s a deep dive but super rewarding, especially if you're into language design or want to really understand how interpreters work under the hood. Totally worth the time.
Positives: * An expert author with a friendly writing style. * Two different interpreters are presented to demonstrate both high level and low level approaches, with all the code shown in the book so you can create the interpreters as you go. * Concepts are explained clearly, and even slightly esoteric concepts (at least the average programmer) like how to implement closures are covered. * Examples of the script to be compiled are provided throughout so you can test your progress as you go.
Negatives: * The second interpreter is written in C, and this is a fairly unforgiving language to debug by modern standards, especially given the heavy use here of preprocessor macros and 'type punning', and that the data you'll see at the time of any crash is itself a semi-compiled form that is hard to make sense of. So if you mistype something, be prepared for a frustrating time as you trawl back through the code snippets one by one to try and see where you might have accidentally replaced a line instead of adding one, or similar. It feels like this section of the book could have been done in C++ without getting in the way of showing low-level implementation details while making the code shorter and easier to debug. * Some concepts probably don't get as much time spent on the theoretical aspects as they deserve. This is especially a problem in the second half when the implementation is more involved and ease of implementation seems to take priority in some cases. Borrowing implementation patterns from Python and Lua was a wise tactic but I would have enjoyed seeing potential alternatives explored that would have helped to illustrate how the theory differs from one specific implementation. * I'm not a fan of the numerous margin notes. It seems to be a common feature in modern technical books but I find it breaks up the flow too much and is distracting.
Crafting Interpreters is a master class in understanding how programming languages work.
Everything about this book is spectacular and meticulously crafted (in fact, you learn all the details about the author's process in this epic post: http://journal.stuffwithstuff.com/202...).
Nystrom guides the reader through a journey of building a programming language (twice!). Along the journey, the reader gets to follow along and write code that is always able to compile between each chapter as the Nystrom explains one core concept after another. But this isn't some dry code project! At each step, the author provides quirky illustrations, fun analogies, nuggets from computing and programming history, and so much more.
The density of information in this book is absolutely massive. The book is also quite long, so the content is veritable treatise on the topic of programming language design.
I rarely give *any* book 5 stars and I've not written a review on Goodreads in years, but it would be such a disservice to other programmers if I didn't share this with others. Crafting Interpreters is easily up there with my other favorite programming books of all time and is a must read for people who want to understand how programming languages really work.
I will just quote Robert blog https://journal.stuffwithstuff.com/20... > Many ask what I’m going to write next, or suggest a topic. I interpret this as a compliment—they like my writing and want more. But it also feels like asking a mom in labor whether she plans to have more kids. I’ve had my legs in the stirrups for six years, so I’m gonna just relax a bit after all the pushing is over before I even think about another book baby.
I applaud the amount of effort and attention of the detail put into this book. Could not compliment enough. Definitely in top 10 technical books on my shelf.
A very good book, but the choice of Java for the first half strikes me as very odd. Too many pages are spent trying to make Java a language you can write a programming language implementation with, which probably would've been better served focusing on the topic by choosing a more suitable language like a functional one (OCaml, Haskell) or an imperative with sum type support (Rust, C++17)
Really nice introduction to compiler design and the tradeoffs between different design choices. In some places it felt like a tedious walk-through of a code base, but it's very well edited though and the code does run. I don't think I spotted a single mistake.
One thing that really bothered me was the insane amount of indirection and abstraction in the code, in the "clean code" style. It's annoying to have to follow multiple layers of calls to single-line functions that could have just been inlined.
An excellent book on how to write interpreters and compilers. I like how it starts with a simple AST based interpreter using Java in the 1st half and then switches to C for a Virtual Machine and compiler in the second half. It even has an implementation of garbage collection! All the code is there to see and understand.
Good book to prove that there's no magic to interpreters.
I didn't like that there were two interpreters or the language choices of Java/C. It would have been nice to have a single language for the whole book, to avoid reimplementing core pieces of the interpreter and boring boilerplate.
This is an extraordinary book that helps you understand how a programming language works and how to develop your own. This book also has a phenomenal community on GitHub with many examples from this book in various programming languages on how to create your own interpreter.
Although not rigorous, a very practical and easy-to-read (and humorous!) introduction to programming a very mature and robust programming language. Lots of good things to learn here, and it is a true workout if you can finish this book. Bravo for this brilliant book :)
I enjoyed reading the book very much. It demystifies how the compiler works and gives deep insights to the reader. I appreciate the discipline and hard work the author put into writing this amazing book.
UPDATE: After going through the files on GitHub, I think someone with previous experience in writing or analyzing parsers would see this book as ordinary. Since I did not have any such experience, I still found it interesting and educational.
Pretty good hands-on introduction to writing a compiler/interpreter. The choice of C as an implementation language makes the second part of the book somewhat messy but otherwise I recommend it.