It is an excellent book and one of the canonical texts on the subject. My only suggestion for the "Lox" language would be to include an implementation of arrays, and preferably also hash/dict arrays. Other than that, the book contains everything you need to know about implementing a programming language.
It's hard to say what "that hard" should be considered, but the book's first half involves Java reflection, which isn't obvious code to port to different languages in my opinion.
Does it? I know it uses metaprogramming (a Java program that outputs another Java program), but that’s probably easier in other languages than in Java. In my Python implementation I was able to significantly simplify that part of the code by using `eval`.
I do remember him using the visitor pattern to implement part of the parser I think. I thought that was kind of an odd choice, especially since it seemed like he was really just trying to avoid Java boilerplate.
Regardless, the book is incredible, and the choice of Java to start with makes sense. Its probably going to be the most universally approachable for everyone, even if they aren't super familiar. C can be pretty overwhelming if you aren't familiar it.
> I do remember him using the visitor pattern to implement part of the parser I think. I thought that was kind of an odd choice, especially since it seemed like he was really just trying to avoid Java boilerplate.
It's used to allow writing a "resolver" and an "interpreter" that both know how to handle every type of node in the AST. It's almost a functional approach, and I actually think it might increase boilerplate because Java is more designed around the object-oriented approach of adding `resolve` and `interpret` methods directly to each node type.
The two approaches result in very different code organisation, though - maybe the visitor approach was easier to explain in prose.
It's been a while since I read it, but I remember him saying something about the more natural (my word not his) approach being a single data structure that you would pass through both components, but he didn't want to do that because Java doesnt really encourage that kind of design, and you have a bunch of boilerplate for each class. It just struck me as an odd choice since the book was more about compiler/interpreter fundamentals, and I feel like the visitor pattern is a bit in the weeds in terms of OOP design.
I wonder if he wrote today if he would have used a Record and done the more straightforward implementation.
I went through the Crafting Interpreters book with modern Java. I posted this on reddit, but I basically used records and sealed interfaces. With modern Java there's no need for visitor pattern.
private void execute(Stmt statement) {
switch (statement) {
case Stmt.Expression expression -> evaluate(expression.expr());
case Stmt.Block block -> executeBlock(block.statements(),
new Environment(environment));
...
public sealed interface Expr permits
Expr.Assign,
Expr.Binary,
Expr.Call,
Expr.Function,
.... more exprs here
Interesting. Almost all my actual experience writing Java is in Java 8, so I'm not super familiar with the modern stuff (other then a few things like Records). I'll have to take a look.
Most of the people I know who write Java would have an aneurysm at seeing a switch statement.
To be clear, that's a critique of the Java mindset, not your code. Lol
It's been a few years now, but there's no real reason to port the Java code directly – you can just read what it's trying to do, and implement that using your language's idioms. I don't remember anything as complex as trying to port reflection.
I understand. I wasn't a Java person when I read that book, yet I still prefer Java over more esoteric options. If Golang is easier for you to understand (no OOP), then I can recommend this one:
Wren, the topic of the post, is positioned as a descendant of Smalltalk, the most OOP language of them all. The author clearly finds the OOP paradigm important.
Yeah, my understanding is that the bytecode interpreter in the second half of the book is essentially a stripped-down version of the Wren virtual machine.
This is awesome. Thank you for sharing. I have been working on a small interpreted language for shell scripts with lots of help from Claude Code. The main idea is to automatically generate the cli interface for the scripts based on function definitions. However, I'm far from a programming languages expert, so I've been a bit hesitant to share my work. Going to give this book a read this week to see how far I am. Thank you!
It is an excellent book and one of the canonical texts on the subject. My only suggestion for the "Lox" language would be to include an implementation of arrays, and preferably also hash/dict arrays. Other than that, the book contains everything you need to know about implementing a programming language.
I wish he would have used C for everything. You need to buyin into Java's whole OOP thing, which I am not a fan of.
It's not too hard to adapt the first half of the book into whatever language you want. People have posted versions in dozens of languages: https://github.com/munificent/craftinginterpreters/wiki/Lox-...
(There are fewer options for the second half, since you need more control over memory management.)
It's hard to say what "that hard" should be considered, but the book's first half involves Java reflection, which isn't obvious code to port to different languages in my opinion.
> the book's first half involves Java reflection
Does it? I know it uses metaprogramming (a Java program that outputs another Java program), but that’s probably easier in other languages than in Java. In my Python implementation I was able to significantly simplify that part of the code by using `eval`.
Yeah I don't recall reflection either.
I do remember him using the visitor pattern to implement part of the parser I think. I thought that was kind of an odd choice, especially since it seemed like he was really just trying to avoid Java boilerplate.
Regardless, the book is incredible, and the choice of Java to start with makes sense. Its probably going to be the most universally approachable for everyone, even if they aren't super familiar. C can be pretty overwhelming if you aren't familiar it.
> I do remember him using the visitor pattern to implement part of the parser I think. I thought that was kind of an odd choice, especially since it seemed like he was really just trying to avoid Java boilerplate.
It's used to allow writing a "resolver" and an "interpreter" that both know how to handle every type of node in the AST. It's almost a functional approach, and I actually think it might increase boilerplate because Java is more designed around the object-oriented approach of adding `resolve` and `interpret` methods directly to each node type.
The two approaches result in very different code organisation, though - maybe the visitor approach was easier to explain in prose.
It's been a while since I read it, but I remember him saying something about the more natural (my word not his) approach being a single data structure that you would pass through both components, but he didn't want to do that because Java doesnt really encourage that kind of design, and you have a bunch of boilerplate for each class. It just struck me as an odd choice since the book was more about compiler/interpreter fundamentals, and I feel like the visitor pattern is a bit in the weeds in terms of OOP design.
I wonder if he wrote today if he would have used a Record and done the more straightforward implementation.
I went through the Crafting Interpreters book with modern Java. I posted this on reddit, but I basically used records and sealed interfaces. With modern Java there's no need for visitor pattern.
Interesting. Almost all my actual experience writing Java is in Java 8, so I'm not super familiar with the modern stuff (other then a few things like Records). I'll have to take a look.
Most of the people I know who write Java would have an aneurysm at seeing a switch statement.
To be clear, that's a critique of the Java mindset, not your code. Lol
It's been a few years now, but there's no real reason to port the Java code directly – you can just read what it's trying to do, and implement that using your language's idioms. I don't remember anything as complex as trying to port reflection.
I understand. I wasn't a Java person when I read that book, yet I still prefer Java over more esoteric options. If Golang is easier for you to understand (no OOP), then I can recommend this one:
https://interpreterbook.com/
BTW, I'm not the author of either of those books, but I have read both of them.
Wren, the topic of the post, is positioned as a descendant of Smalltalk, the most OOP language of them all. The author clearly finds the OOP paradigm important.
I recently did a dual implementation of a simple language in Java/C for educational purposes:
https://github.com/codr7/shi
An optional challenge gives an implementation of arrays for jlox at least: https://github.com/munificent/craftinginterpreters/blob/4a84...
and he wrote Game Programming Patterns [0]
[0] https://gameprogrammingpatterns.com/
Knowing this is the author makes me 1000% more interested in Wren. What a great book!
Yeah, my understanding is that the bytecode interpreter in the second half of the book is essentially a stripped-down version of the Wren virtual machine.
This is awesome. Thank you for sharing. I have been working on a small interpreted language for shell scripts with lots of help from Claude Code. The main idea is to automatically generate the cli interface for the scripts based on function definitions. However, I'm far from a programming languages expert, so I've been a bit hesitant to share my work. Going to give this book a read this week to see how far I am. Thank you!
Take a look at how Nushell does this, it's quite neat: https://www.nushell.sh/book/custom_commands.html#documenting...
That's excellent. Somewhat similar to the syntax I went with, but most likely much better implemented. I'm going to give it a go. Thank you!
Is Bob still involved (in Wren)?
I thought his focus was Dart these days given being employed by Google.