Repository for the book "Crafting Interpreters"

Overview

This is the repo used for the in-progress book "Crafting Interpreters". It contains the Markdown text of the book, full implementations of both interpreters, as well as the build system to weave the two together into the final site.

If you find an error or have a suggestion, please do file an issue here. Thank you!

Contributing

One of the absolute best things about writing a book online and putting it out there before it's done is that people like you have been kind enough to give me feedback, point out typos, and find other errors or unclear text.

If you'd like to do that, great! You can just file bugs here on the repo, or send a pull request if you're so inclined. If you want to send a pull request, but don't want to get the build system set up to regenerate the HTML too, don't worry about it. I'll do that when I pull it in.

Ports and implementations

Another way to get involved is by sharing your own implementation of Lox. Ports to other languages are particularly useful since not every reader likes Java and C. Feel free to add your Lox port or implementation to the wiki:

Building Stuff

I am a terribly forgetful, error-prone mammal, so I automated as much as I could.

Prerequisites

I develop on an OS X machine, but any POSIX system should work too. With a little extra effort, you should be able to get this working on Windows as well, though I can't help you out much.

Most of the work is orchestrated by make. The build scripts, test runner, and other utilities are all written in Dart. Instructions to install Dart are here. Once you have Dart installed and on your path, run:

$ make get

This downloads all of the packages used by the build and test scripts.

In order to compile the two interpreters, you also need a C compiler on your path as well as javac.

Building

Once you've got that setup, try:

$ make

If everything is working, that will generate the site for the book as well as compiling the two interpreters clox and jlox. You can run either interpreter right from the root of the repo:

$ ./clox
$ ./jlox

Hacking on the book

The Markdown and snippets of source code are woven together into the final HTML using a hand-written static site generator that started out as a single tiny Python script for my first book and somehow grew into something approximating a real program.

The generated HTML is committed in the repo under site/. It is built from a combination of Markdown for prose, which lives in book/, and snippets of code that are weaved in from the Java and C implementations in java/ and c/. (All of those funny looking comments in the source code are how it knows which snippet goes where.)

The script that does all the magic is tool/bin/build.dart. You can run that directly, or run:

$ make book

That generates the entire site in one batch. If you are incrementally working on it, you'll want to run the development server:

$ make serve

This runs a little HTTP server on localhost rooted at the site/ directory. Any time you request a page, it regenerates any files whose sources have been changed, including Markdown files, interpreter source files, templates, and assets. Just let that keep running, edit files locally, and refresh your browser to see the changes.

Building the interpreters

You can build each interpreter like so:

$ make clox
$ make jlox

This builds the final version of each interpreter as it appears at the end of its part in the book.

You can also see what the interpreters look like at the end of each chapter. (I use this to make sure they are working even in the middle of the book.) This is driven by a script, tool/bin/split_chapters.dart that uses the same comment markers for the code snippets to determine which chunks of code are present in each chapter. It takes only the snippets that have been seen by the end of each chapter and produces a new copy of the source in gen/, one directory for each chapter's code. (These are also an easier way to view the source code since they have all of the distracting marker comments stripped out.)

Then, each of those can be built separately. Run:

$ make c_chapters

And in the build/ directory, you'll get an executable for each chapter, like chap14_chunks, etc. Likewise:

$ make java_chapters

This compiles the Java code to classfiles in build/gen/ in a subdirectory for each chapter.

Testing

I have a full Lox test suite that I use to ensure the interpreters in the book do what they're supposed to do. The test cases live in test/. The Dart program tool/bin/test.dart is a test runner that runs each of those test files on a Lox interpreter, parses the result, and validates that that the test does what it's expected to do.

There are various interpreters you can run the tests against:

$ make test       # The final versions of clox and jlox.
$ make test_clox  # The final version of clox.
$ make test_jlox  # The final version of jlox.
$ make test_c     # Every chapter's version of clox.
$ make test_java  # Every chapter's version of jlox.
$ make test_all   # All of the above.

Testing your implementation

You are welcome to use the test suite and the test runner to test your own Lox implementation. The test runner is at tool/bin/test.dart and can be given a custom interpreter executable to run using --interpreter. For example, if you had an interpreter executable at my_code/boblox, you could test it like:

$ dart tool/bin/test.dart clox --interpreter my_code/boblox

You still need to tell it which suite of tests to run because that determines the test expectations. If your interpreter should behave like jlox, use "jlox" as the suite name. If it behaves like clox, use "clox". If your interpreter is only complete up to the end of one of the chapters in the book, you can use that chapter as the suite, like "chap10_functions". See the Makefile for the names of all of the chapters.

If your interpreter needs other command line arguments passed to use, pass them to the test runner using --arguments and it will forward to your interpreter.

Repository Layout

  • asset/ – Sass files and jinja2 templates used to generate the site.
  • book/ - Markdown files for the text of each chapter.
  • build/ - Intermediate files and other build output (except for the site itself) go here. Not committed to Git.
  • c/ – Source code of clox, the interpreter written in C. Also contains an XCode project, if that's your thing.
  • gen/ – Java source files generated by GenerateAst.java go here. Not committed.
  • java/ – Source code of jlox, the interpreter written in Java.
  • note/ – Various research, notes, TODOs, and other miscellanea.
  • note/answers – Sample answers for the challenges. No cheating!
  • site/ – The final generated site. The contents of this directory directly mirror craftinginterpreters.com. Most content here is generated by build.py, but fonts, images, and JS only live here. Everything is committed, even the generated content.
  • test/ – Test cases for the Lox implementations.
  • tool/ – Dart package containing the build, test, and other scripts.
Comments
  • Any hints implementing break and continue?

    Any hints implementing break and continue?

    I had trouble implementing break statement. I already added the tokens and statements with zero parameters (maybe there should be some - probably some context). I don't know how you would check if break is within a loop. I thought maybe check the tokens, but that would be tedious. Also I don't know how you would break out of a loop which is visited as another statement. Thought about exceptions but I know that is not the right way. So maybe you can give me some hints for these. Maybe it would be useful to put them in a book too because currently a note in challenge only describes what break is.

    opened by fsacer 13
  • Marginal Collisions in the Typesetting

    Marginal Collisions in the Typesetting

    In some layouts, the "margin grafiti" (as Knuth would call it) and the source file annotations overlap.

    See the attached screenshot, where main.c\n add to top of file overlaps with "The code tests for one and two arguments, ..." in the margins on the right-hand-side.

    layout-nightmare

    opened by pqnelson 10
  • Typo: chapter 2.3

    Typo: chapter 2.3

    This line in chapter 2.3 may need adjustment:

    So go has a compiler, is an interpreter, and is also a compiler.

    Also, I am by no means an expert on this field (that's why I am reading the book!), but is go really an interpreter, or is it the OS/CPU which actually interprets the go generated executable. Whereby the command, go run acts as a wrapper to compile, then start the interpretation which is done by the OS/CPU?

    Anyway, thanks again for another great book!

    opened by scottwillmoore 8
  • Invalid section of code?

    Invalid section of code?

    @munificent Section https://www.craftinginterpreters.com/statements-and-state.html#assignment-syntax shows this block of code:

      private Expr assignment() {
        Expr expr = equality();
    
        if (match(EQUAL)) {
          Token equals = previous();
          Expr value = assignment();
    
          if (expr instanceof Expr.Variable) {
            Token name = ((Expr.Variable)expr).name;
            return new Expr.Assign(name, value);
          }
    
          error(equals, "Invalid assignment target."); 
        }
    
        return expr;
      }
    

    However, my IDE warns that the "Result of 'error()' is not thrown", so I think it should say:

          . . .
          throw error(equals, "Invalid assignment target."); 
          . . .
    

    What do you think?

    P.S. This book is excellent! I'm enjoying reading it so far and it's shed a lot of light for me on how compilers and tools like ANTLR work. I wish you all the best with writing the rest.

    opened by jbduncan 7
  • Typo in Chapter 3: The Lox Language - Closures snippet?

    Typo in Chapter 3: The Lox Language - Closures snippet?

    Section 3.8.1, Closures, includes this code snippet to demonstrate passing around a function as an argument:

    print identity(addPair)(1, 2); // Prints "3".

    Can that be right? Aren't the parentheses misplaced? Shouldn't this be:

    print identity(addPair(1, 2)); // Prints "3".

    opened by bhagerty 7
  • Chapter 1: Challenges,  #3, seriously?

    Chapter 1: Challenges, #3, seriously?

    I open up a hoopyfroop book and read the introductory chapter. It says, "hey, we're going to make a couple languages in Java, and later, we will learn about the structures to do it in C. No problem; we'll take it slow". Then I get to the challenges, #1 is a 'look at the repo and notice all the little languages', #2 is 'go get a Java Environment set up, you can figure that out.', and then we get #3: 'oh, also set up a C environment because we might need that if you stay with the book for a dozen chapters, and you should write some link lists in it, with helper functions, and tests.'

    Are you sure it's not a typo and should say: "3. As a challenge, implement your own version of Linux in C. "

    opened by merriam 7
  • Remove Expr.Grouping

    Remove Expr.Grouping

    Parenthesis are here to allow a user to specify how to parse something, once the grammar is parsed, there is no need for an AST node that represent the fact that the input file has to be parsed in a certain way.

    So Expr.Grouping and the corresponding visits that does nothing can be removed.

    opened by forax 7
  • Missing information about status.

    Missing information about status.

    The document is copyright 2015 but only has the first 4 chapters. The rest say "coming soon!" but that's obviously not true. Please do your readers a favor and include information about the actual status and progress of this book and when they can realistically expect to see the rest of it. As it is, reading this is a waste of time when so much of the document is missing. Also it's a waste of time to post issues about the content, which I had intended to do.

    opened by jibal 7
  • Chapter 4 End State

    Chapter 4 End State

    And with that, we now have a complete scanner for the entire Lox lexical grammar. Fire up the REPL and type in some valid and invalid code. Does it produce the tokens you expect? - End of Chapter 4.7

    What is the supposed end state for this chapter? My examples appear to have tokens with memory addresses. Is that what we should have at this stage?

    > "Hello World"
    [email protected]
    [email protected]
    > Hello World
    [email protected]
    [email protected]
    [email protected]
    > 1.2 + 2.3
    [email protected]
    [email protected]
    [email protected]
    [email protected]
    > 1 + 2
    [email protected]
    [email protected]
    [email protected]
    [email protected]
    

    Thanks for reading!

    opened by philip-sparks 6
  • Module system in Lox

    Module system in Lox

    Thank you for your amazing book :D

    I have currently learned to write my interpreter following the book. But I don't know how to implement a module system like Python. I couldn't find any tutorials on the internet.

    I appreciate it if you give me a couple of hints.

    discussion 
    opened by bichanna 6
  • Expression result not printed after execution

    Expression result not printed after execution

    In Repl mode, It's always better to be interactive and show how easy and fun using a programming language can be. After trying current version of Lox, figured out you need to use print statement to figure out what is the result of an expression.

    By expression I mean return value of function, Initial expression of variable and direct coding like 1 / 2 .

    Issue current-version :

    10 + 10 ; ..

    opened by mhmdvoid 6
  • clox functionality is not entirely unchanged after section 24.3

    clox functionality is not entirely unchanged after section 24.3

    In the last paragraph of section 24.3, the book reads: "Assuming we did all of that correctly, we got clox back to a runnable state. Fire it up and it does... exactly what it did before.".

    This is not entirely true. In interpret, the initial function is pushed to the stack, and at this point it's only popped if a runtime error occurs. This means that successive invocations of the REPL without errors will have issues with locals, as the bytecode only expects there to be one value in the frame when the bytecode starts being executed.

    The issue is fixed in 24.5.4 with the new code for OP_RETURN, which pops the value from the stack.

    It might be worth changing the wording, since this can cause some confusion for readers that are following along, and want to test their code after section 24.3.

    opened by danielbendix 0
  • Added link to content page

    Added link to content page

    I'm working through the book, and I'm finding it a bit awkward to navigate back to the contents page. So I have added a link to contents from the floating navbars.

    This looks fine when the navbar is stretched. However, on some pages, or when you scroll down, it squashes, which doesn't look as good. Maybe someone who knows the project better than me can improve on this?

    image   This looks fine, IMO.

    image   Scrolling down... not quite as nice?

    image   The final page also doesn't look quite right.

    opened by tkburis 0
  • SegFault @ 24.5.3 in REPL

    SegFault @ 24.5.3 in REPL

    Section 24.5.3 has to do with printing stack traces. It ends with entering in a broken program to demonstrate the stack trace.

    fun a() { b(); }
    fun b() { c(); }
    fun c() {
      c("too", "many");
    }
    
    a();
    

    If you run the program from the REPL by creating each definition in turn then at this point in the chapter you will produce a segfault after you enter in the second function. (Really it works with any pair of statements you enter.) This is fixed in the next section (24.5.4) because we add in return values so all's well that ends well.

    However, I would recommend adding a note next to the example that warns the user that they will get a SegFault from the REPL, but not from a file. (It could even include a cheeky author comment asking the reader to consider why this might be the case.)

    I burned an hour trying to figure out why the vm.frameCount underflowed (That's C, baby!) and where I deviated from the book as written. Turns out everything was working as expected. I just needed to keep following the book.


    Thanks for writing this lovely book and putting it online! Really appreciate it!

    opened by felix-alonso 0
  • clox throws an error on the string_equality benchmark

    clox throws an error on the string_equality benchmark

    To reproduce:

    make clox
    ./clox test/benchmark/string_equality.lox
    

    Output:

    [line 32] Error at 'a4': Too many constants in one chunk.
    [line 32] Error at 'a7': Too many constants in one chunk.
    [line 32] Error at 'a5': Too many constants in one chunk.
    [line 32] Error at 'a7': Too many constants in one chunk.
    [line 32] Error at 'a6': Too many constants in one chunk.
    [line 32] Error at 'a7': Too many constants in one chunk.
    [line 32] Error at 'a7': Too many constants in one chunk.
    [line 32] Error at 'a7': Too many constants in one chunk.
    [line 32] Error at 'a8': Too many constants in one chunk.
    ...
    

    The same benchmark works correctly with jlox because it doesn't enforce limits on constants, but it would be great if the benchmark was updated to something that could run on both, so that they could be compared more easily.

    opened by ajeetdsouza 0
  • Chapter 20 (Hash tables) challenge 1 solution bug

    Chapter 20 (Hash tables) challenge 1 solution bug

    The bold code fragment should be IS_EMPTY. Otherwise the key nil would not be possible in a hash table.

    +bool tableGet(Table* table, Value key, Value* value) { if (table->entries == NULL) return false;

    Entry* entry = findEntry(table->entries, table->capacity, key);

    • if (entry->key == NULL) return false;
    • if (IS_NIL(entry->key)) return false;

      *value = entry->value; return true;

    opened by bayerf42 0
Owner
Bob Nystrom
Programming language developer, ex-game developer, UI nerd, author of "Game Programming Patterns" and "Crafting Interpreters".
Bob Nystrom
A place to collaborate on code for the Embedded.fm book club. Currently reading "STM32 ARM Programming for Embedded Systems".

Welcome to the Book Club Code site! This is a place for the Embedded.fm book club to collaborate and learn together. Repo Structure Guide Top-level fo

Peter Griffin 11 Jul 21, 2022
C++ Premier plus 6th edition book solved exercise.

c-premier-plus-6th-edition-solved-exercise C++ Premier plus 6th edition book exercise solutions. These exercise solved by me when i learning c++, so d

Zaid Rao 2 Nov 6, 2022
Source code for the "C Unleashed" book by Richard Heathfield, Lawrence Kirby, et al.

Source code from the book "C Unleashed" "C Unleashed" was written by Richard Heathfield, Lawrence Kirby and several other collaborators and published

Eli Bendersky 51 Dec 13, 2022
Resolução de exercícios do e-book 300 ideias para programar

Repositório 300 ideias para programar Saudações! Este repositório é dedicado a resolução dos exercícios do e-book 300 IDÉIAS PARA PROGRAMAR COMPUTADOR

Code Brasil 2 Jan 1, 2022
Software to support people learning OpenMP with our book

Software to support people learning OpenMP with our book ... The OpenMP Common Core: Making OpenMP Simple Again

Tim Mattson 53 Dec 14, 2022
This repository is for everyone for Hacktoberfest 2021. Anyone can contribute anything for your Swags (T- Shirt), must be relevant that can add some value to this repository.

Hacktober Fest 2021 For Everyone! Upload Projects or Different Types of Programs in any Language Use this project to make your first contribution to a

Mahesh Jain 174 Dec 27, 2022
This Repository is created to help fellow coders learn open source contributions. This Repository is created for Hacktoberfest 2021

Hacktoberfest 2021 Follow the README below to get started! This Repository is created to help fellow coders learn open source contributions This Repos

Somesh Debnath 6 Oct 24, 2022
This repository is a study repository to implement the LCD 16x2 in my project below

This repository is a study repository to implement the LCD 16x2 in my project below. Index ?? About ?? Functionalities ?? Deploy ?? Requirements ?? Pi

Rickelme Dias 3 Jun 7, 2022
This repository is used for automatic calibration between high resolution LiDAR and camera in targetless scenes.

livox_camera_calib livox_camera_calib is a robust, high accuracy extrinsic calibration tool between high resolution LiDAR (e.g. Livox) and camera in t

HKU-Mars-Lab 491 Dec 29, 2022
Learn how to connect your Flexispot (LoctekMotion) desk to the internet. This repository contains a collection of scripts to get your started, combined with research and instructions.

(image source: Windows Central) Turn your LoctekMotion/FlexiSpot desk into a smart desk Recently I acquired a new standing desk from FlexiSpot. During

Mick Vleeshouwer 216 Dec 28, 2022
This repository contains toy ImPlot applications that demonstrate some of the library's functionality

ImPlot Demos This repository contains toy ImPlot applications that demonstrate some of the library's functionality.

Evan Pezent 83 Dec 28, 2022
This repository is to explain how the SN74HC595 register works

Register_SN74HC595 This repository is to explain how the SN74HC595 register works Aujourd’hui on va apprendre à comment augmenter le nombre de sortie

mugiwarra229 5 Jun 8, 2021
Southwest University Lanqiao Cup Training Repository, April 2021

2021 Southwest University Lanqiao Cup Trainning Course Summary This repository is using for LanqiaoCup Competition on 18th, April, 2021 How to start W

西南大学ACM实验室 9 Apr 15, 2021
Officially repository Competitive Programming ID

Competitive Programming ID Official repository of Competitive Programming ID (https://t.me/CP_ID) Codewars Stats -------------------------------------

DVL ナンダ 3 Nov 27, 2022
This repository is to share the EdgeAI Lab with Microcontrollers Series material to the entire community

This repository is to share the EdgeAI Lab with Microcontrollers Series material to the entire community. We will share documents, presentations and source code of two demo applications.

Machine Learning Tokyo 15 Oct 23, 2021
the first ever open source zombie killcam mod for bo2 zombies. this repository is the original mod.

BO2 T6ZM Killcams (+ Mod Menu) my zombie killcam mod that is a work-in-progress and open sourced. this may work off plutonium but this was only suppor

m 5 Dec 14, 2022
Repository created to store a C function library to use in 42 School

Libft of 42. Make with ❤︎ for Luiz Cezario ?? Index What's this Repo? List of Functions Technologies How to Run Find a Bug? Or somenthing need to chan

Luiz lima cezario 9 Aug 19, 2022
This repository provides you the material of installation the Catalana Hackintosh

VivoBook Asus X542UQ laptop Catalina 10.15.7 Hackintosh This repository provides you the material of installation the Catalana Hackintosh with Opencor

Vlad Tatarinov 2 Oct 9, 2021
A repository for Dsa solutions and approaches 📚📕

Coffee and Code ?? Coffee and Code is a Question Bank that provides solving patterns and resources along with solutions in diffrent language to help y

null 16 Nov 28, 2021